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 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
48 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
49 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "1", "light equalizing: ensure at least this ambient/diffuse ratio"};
50 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
51 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
53 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
55 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"};
56 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
57 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
58 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
59 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)"};
60 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
61 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
62 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"};
63 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"};
64 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
65 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"};
66 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"};
67 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"};
68 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
69 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
70 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
71 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
72 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
73 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
74 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
75 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
76 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
77 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
78 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
79 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
80 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."};
81 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
82 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
83 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
84 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "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."};
85 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
86 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
87 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"};
88 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "4", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
89 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
90 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
92 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
93 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
94 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
95 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
96 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
97 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
98 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
99 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
101 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)"};
103 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
104 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)"};
105 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
106 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
107 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
108 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
109 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)"};
110 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)"};
111 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)"};
112 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)"};
113 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)"};
115 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)"};
116 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
117 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"};
118 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
119 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
121 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
122 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
123 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
124 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
126 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
127 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
128 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
129 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
130 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
131 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
132 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
134 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
135 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
136 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
137 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)"};
139 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"};
141 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"};
143 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
145 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
146 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
147 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"};
148 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
149 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
150 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
151 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
153 extern cvar_t v_glslgamma;
155 extern qboolean v_flipped_state;
157 static struct r_bloomstate_s
162 int bloomwidth, bloomheight;
164 int screentexturewidth, screentextureheight;
165 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
167 int bloomtexturewidth, bloomtextureheight;
168 rtexture_t *texture_bloom;
170 // arrays for rendering the screen passes
171 float screentexcoord2f[8];
172 float bloomtexcoord2f[8];
173 float offsettexcoord2f[8];
175 r_viewport_t viewport;
179 r_waterstate_t r_waterstate;
181 /// shadow volume bsp struct with automatically growing nodes buffer
184 rtexture_t *r_texture_blanknormalmap;
185 rtexture_t *r_texture_white;
186 rtexture_t *r_texture_grey128;
187 rtexture_t *r_texture_black;
188 rtexture_t *r_texture_notexture;
189 rtexture_t *r_texture_whitecube;
190 rtexture_t *r_texture_normalizationcube;
191 rtexture_t *r_texture_fogattenuation;
192 rtexture_t *r_texture_gammaramps;
193 unsigned int r_texture_gammaramps_serial;
194 //rtexture_t *r_texture_fogintensity;
196 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
197 unsigned int r_numqueries;
198 unsigned int r_maxqueries;
200 typedef struct r_qwskincache_s
202 char name[MAX_QPATH];
203 skinframe_t *skinframe;
207 static r_qwskincache_t *r_qwskincache;
208 static int r_qwskincache_size;
210 /// vertex coordinates for a quad that covers the screen exactly
211 const float r_screenvertex3f[12] =
219 extern void R_DrawModelShadows(void);
221 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
224 for (i = 0;i < verts;i++)
235 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
238 for (i = 0;i < verts;i++)
248 // FIXME: move this to client?
251 if (gamemode == GAME_NEHAHRA)
253 Cvar_Set("gl_fogenable", "0");
254 Cvar_Set("gl_fogdensity", "0.2");
255 Cvar_Set("gl_fogred", "0.3");
256 Cvar_Set("gl_foggreen", "0.3");
257 Cvar_Set("gl_fogblue", "0.3");
259 r_refdef.fog_density = 0;
260 r_refdef.fog_red = 0;
261 r_refdef.fog_green = 0;
262 r_refdef.fog_blue = 0;
263 r_refdef.fog_alpha = 1;
264 r_refdef.fog_start = 0;
265 r_refdef.fog_end = 0;
268 static void R_BuildBlankTextures(void)
270 unsigned char data[4];
271 data[2] = 128; // normal X
272 data[1] = 128; // normal Y
273 data[0] = 255; // normal Z
274 data[3] = 128; // height
275 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
280 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
285 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
290 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
293 static void R_BuildNoTexture(void)
296 unsigned char pix[16][16][4];
297 // this makes a light grey/dark grey checkerboard texture
298 for (y = 0;y < 16;y++)
300 for (x = 0;x < 16;x++)
302 if ((y < 8) ^ (x < 8))
318 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
321 static void R_BuildWhiteCube(void)
323 unsigned char data[6*1*1*4];
324 memset(data, 255, sizeof(data));
325 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
328 static void R_BuildNormalizationCube(void)
332 vec_t s, t, intensity;
334 unsigned char data[6][NORMSIZE][NORMSIZE][4];
335 for (side = 0;side < 6;side++)
337 for (y = 0;y < NORMSIZE;y++)
339 for (x = 0;x < NORMSIZE;x++)
341 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
342 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
377 intensity = 127.0f / sqrt(DotProduct(v, v));
378 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
379 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
380 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
381 data[side][y][x][3] = 255;
385 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
388 static void R_BuildFogTexture(void)
392 unsigned char data1[FOGWIDTH][4];
393 //unsigned char data2[FOGWIDTH][4];
396 r_refdef.fogmasktable_start = r_refdef.fog_start;
397 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
398 r_refdef.fogmasktable_range = r_refdef.fogrange;
399 r_refdef.fogmasktable_density = r_refdef.fog_density;
401 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
402 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
404 d = (x * r - r_refdef.fogmasktable_start);
405 if(developer.integer >= 100)
406 Con_Printf("%f ", d);
408 if (r_fog_exp2.integer)
409 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
411 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
412 if(developer.integer >= 100)
413 Con_Printf(" : %f ", alpha);
414 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
415 if(developer.integer >= 100)
416 Con_Printf(" = %f\n", alpha);
417 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
420 for (x = 0;x < FOGWIDTH;x++)
422 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
427 //data2[x][0] = 255 - b;
428 //data2[x][1] = 255 - b;
429 //data2[x][2] = 255 - b;
432 if (r_texture_fogattenuation)
434 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
435 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
439 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);
440 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
444 static const char *builtinshaderstring =
445 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
446 "// written by Forest 'LordHavoc' Hale\n"
448 "// enable various extensions depending on permutation:\n"
450 "#ifdef USESHADOWMAPRECT\n"
451 "# extension GL_ARB_texture_rectangle : enable\n"
454 "#ifdef USESHADOWMAP2D\n"
455 "# ifdef GL_EXT_gpu_shader4\n"
456 "# extension GL_EXT_gpu_shader4 : enable\n"
458 "# ifdef GL_ARB_texture_gather\n"
459 "# extension GL_ARB_texture_gather : enable\n"
461 "# ifdef GL_AMD_texture_texture4\n"
462 "# extension GL_AMD_texture_texture4 : enable\n"
467 "#ifdef USESHADOWMAPCUBE\n"
468 "# extension GL_EXT_gpu_shader4 : enable\n"
471 "#ifdef USESHADOWSAMPLER\n"
472 "# extension GL_ARB_shadow : enable\n"
475 "// common definitions between vertex shader and fragment shader:\n"
477 "//#ifdef __GLSL_CG_DATA_TYPES\n"
478 "//# define myhalf half\n"
479 "//# define myhalf2 half2\n"
480 "//# define myhalf3half3\n"
481 "//# define myhalf4 half4\n"
483 "# define myhalf float\n"
484 "# define myhalf2 vec2\n"
485 "# define myhalf3 vec3\n"
486 "# define myhalf4 vec4\n"
489 "#ifdef MODE_DEPTH_OR_SHADOW\n"
491 "# ifdef VERTEX_SHADER\n"
494 " gl_Position = ftransform();\n"
499 "#ifdef MODE_SHOWDEPTH\n"
500 "# ifdef VERTEX_SHADER\n"
503 " gl_Position = ftransform();\n"
504 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
507 "# ifdef FRAGMENT_SHADER\n"
510 " gl_FragColor = gl_Color;\n"
514 "#else // !MODE_SHOWDEPTH\n"
516 "#ifdef MODE_POSTPROCESS\n"
517 "# ifdef VERTEX_SHADER\n"
520 " gl_FrontColor = gl_Color;\n"
521 " gl_Position = ftransform();\n"
522 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
524 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
528 "# ifdef FRAGMENT_SHADER\n"
530 "uniform sampler2D Texture_First;\n"
532 "uniform sampler2D Texture_Second;\n"
534 "#ifdef USEGAMMARAMPS\n"
535 "uniform sampler2D Texture_GammaRamps;\n"
537 "#ifdef USESATURATION\n"
538 "uniform float Saturation;\n"
540 "#ifdef USEVIEWTINT\n"
541 "uniform vec4 TintColor;\n"
543 "//uncomment these if you want to use them:\n"
544 "uniform vec4 UserVec1;\n"
545 "// uniform vec4 UserVec2;\n"
546 "// uniform vec4 UserVec3;\n"
547 "// uniform vec4 UserVec4;\n"
548 "// uniform float ClientTime;\n"
549 "uniform vec2 PixelSize;\n"
552 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
554 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
556 "#ifdef USEVIEWTINT\n"
557 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
560 "#ifdef USEPOSTPROCESSING\n"
561 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
562 "// 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"
563 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
564 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
565 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
566 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
567 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
568 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
571 "#ifdef USESATURATION\n"
572 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
573 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
574 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
575 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
578 "#ifdef USEGAMMARAMPS\n"
579 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
580 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
581 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
588 "#ifdef MODE_GENERIC\n"
589 "# ifdef VERTEX_SHADER\n"
592 " gl_FrontColor = gl_Color;\n"
593 "# ifdef USEDIFFUSE\n"
594 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
596 "# ifdef USESPECULAR\n"
597 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
599 " gl_Position = ftransform();\n"
602 "# ifdef FRAGMENT_SHADER\n"
604 "# ifdef USEDIFFUSE\n"
605 "uniform sampler2D Texture_First;\n"
607 "# ifdef USESPECULAR\n"
608 "uniform sampler2D Texture_Second;\n"
613 " gl_FragColor = gl_Color;\n"
614 "# ifdef USEDIFFUSE\n"
615 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
618 "# ifdef USESPECULAR\n"
619 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
621 "# ifdef USECOLORMAPPING\n"
622 " gl_FragColor *= tex2;\n"
625 " gl_FragColor += tex2;\n"
627 "# ifdef USEVERTEXTEXTUREBLEND\n"
628 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
633 "#else // !MODE_GENERIC\n"
635 "varying vec2 TexCoord;\n"
636 "#ifdef USEVERTEXTEXTUREBLEND\n"
637 "varying vec2 TexCoord2;\n"
639 "varying vec2 TexCoordLightmap;\n"
641 "#ifdef MODE_LIGHTSOURCE\n"
642 "varying vec3 CubeVector;\n"
645 "#ifdef MODE_LIGHTSOURCE\n"
646 "varying vec3 LightVector;\n"
648 "#ifdef MODE_LIGHTDIRECTION\n"
649 "varying vec3 LightVector;\n"
652 "varying vec3 EyeVector;\n"
654 "varying vec3 EyeVectorModelSpace;\n"
657 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
658 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
659 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
661 "#ifdef MODE_WATER\n"
662 "varying vec4 ModelViewProjectionPosition;\n"
664 "#ifdef MODE_REFRACTION\n"
665 "varying vec4 ModelViewProjectionPosition;\n"
667 "#ifdef USEREFLECTION\n"
668 "varying vec4 ModelViewProjectionPosition;\n"
675 "// vertex shader specific:\n"
676 "#ifdef VERTEX_SHADER\n"
678 "uniform vec3 LightPosition;\n"
679 "uniform vec3 EyePosition;\n"
680 "uniform vec3 LightDir;\n"
682 "// 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"
686 " gl_FrontColor = gl_Color;\n"
687 " // copy the surface texcoord\n"
688 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
689 "#ifdef USEVERTEXTEXTUREBLEND\n"
690 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
692 "#ifndef MODE_LIGHTSOURCE\n"
693 "# ifndef MODE_LIGHTDIRECTION\n"
694 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
698 "#ifdef MODE_LIGHTSOURCE\n"
699 " // transform vertex position into light attenuation/cubemap space\n"
700 " // (-1 to +1 across the light box)\n"
701 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
703 " // transform unnormalized light direction into tangent space\n"
704 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
705 " // normalize it per pixel)\n"
706 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
707 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
708 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
709 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
712 "#ifdef MODE_LIGHTDIRECTION\n"
713 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
714 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
715 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
718 " // transform unnormalized eye direction into tangent space\n"
720 " vec3 EyeVectorModelSpace;\n"
722 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
723 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
724 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
725 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
727 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
728 " VectorS = gl_MultiTexCoord1.xyz;\n"
729 " VectorT = gl_MultiTexCoord2.xyz;\n"
730 " VectorR = gl_MultiTexCoord3.xyz;\n"
733 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
734 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
735 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
736 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
739 "// transform vertex to camera space, using ftransform to match non-VS\n"
741 " gl_Position = ftransform();\n"
743 "#ifdef MODE_WATER\n"
744 " ModelViewProjectionPosition = gl_Position;\n"
746 "#ifdef MODE_REFRACTION\n"
747 " ModelViewProjectionPosition = gl_Position;\n"
749 "#ifdef USEREFLECTION\n"
750 " ModelViewProjectionPosition = gl_Position;\n"
754 "#endif // VERTEX_SHADER\n"
759 "// fragment shader specific:\n"
760 "#ifdef FRAGMENT_SHADER\n"
762 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
763 "uniform sampler2D Texture_Normal;\n"
764 "uniform sampler2D Texture_Color;\n"
765 "uniform sampler2D Texture_Gloss;\n"
766 "uniform sampler2D Texture_Glow;\n"
767 "uniform sampler2D Texture_SecondaryNormal;\n"
768 "uniform sampler2D Texture_SecondaryColor;\n"
769 "uniform sampler2D Texture_SecondaryGloss;\n"
770 "uniform sampler2D Texture_SecondaryGlow;\n"
771 "uniform sampler2D Texture_Pants;\n"
772 "uniform sampler2D Texture_Shirt;\n"
773 "uniform sampler2D Texture_FogMask;\n"
774 "uniform sampler2D Texture_Lightmap;\n"
775 "uniform sampler2D Texture_Deluxemap;\n"
776 "uniform sampler2D Texture_Refraction;\n"
777 "uniform sampler2D Texture_Reflection;\n"
778 "uniform sampler2D Texture_Attenuation;\n"
779 "uniform samplerCube Texture_Cube;\n"
781 "#define showshadowmap 0\n"
783 "#ifdef USESHADOWMAPRECT\n"
784 "# ifdef USESHADOWSAMPLER\n"
785 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
787 "uniform sampler2DRect Texture_ShadowMapRect;\n"
791 "#ifdef USESHADOWMAP2D\n"
792 "# ifdef USESHADOWSAMPLER\n"
793 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
795 "uniform sampler2D Texture_ShadowMap2D;\n"
799 "#ifdef USESHADOWMAPVSDCT\n"
800 "uniform samplerCube Texture_CubeProjection;\n"
803 "#ifdef USESHADOWMAPCUBE\n"
804 "# ifdef USESHADOWSAMPLER\n"
805 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
807 "uniform samplerCube Texture_ShadowMapCube;\n"
811 "uniform myhalf3 LightColor;\n"
812 "uniform myhalf3 AmbientColor;\n"
813 "uniform myhalf3 DiffuseColor;\n"
814 "uniform myhalf3 SpecularColor;\n"
815 "uniform myhalf3 Color_Pants;\n"
816 "uniform myhalf3 Color_Shirt;\n"
817 "uniform myhalf3 FogColor;\n"
819 "uniform myhalf4 TintColor;\n"
822 "//#ifdef MODE_WATER\n"
823 "uniform vec4 DistortScaleRefractReflect;\n"
824 "uniform vec4 ScreenScaleRefractReflect;\n"
825 "uniform vec4 ScreenCenterRefractReflect;\n"
826 "uniform myhalf4 RefractColor;\n"
827 "uniform myhalf4 ReflectColor;\n"
828 "uniform myhalf ReflectFactor;\n"
829 "uniform myhalf ReflectOffset;\n"
831 "//# ifdef MODE_REFRACTION\n"
832 "//uniform vec4 DistortScaleRefractReflect;\n"
833 "//uniform vec4 ScreenScaleRefractReflect;\n"
834 "//uniform vec4 ScreenCenterRefractReflect;\n"
835 "//uniform myhalf4 RefractColor;\n"
836 "//# ifdef USEREFLECTION\n"
837 "//uniform myhalf4 ReflectColor;\n"
840 "//# ifdef USEREFLECTION\n"
841 "//uniform vec4 DistortScaleRefractReflect;\n"
842 "//uniform vec4 ScreenScaleRefractReflect;\n"
843 "//uniform vec4 ScreenCenterRefractReflect;\n"
844 "//uniform myhalf4 ReflectColor;\n"
849 "uniform myhalf3 GlowColor;\n"
850 "uniform myhalf SceneBrightness;\n"
852 "uniform float OffsetMapping_Scale;\n"
853 "uniform float OffsetMapping_Bias;\n"
854 "uniform float FogRangeRecip;\n"
856 "uniform myhalf AmbientScale;\n"
857 "uniform myhalf DiffuseScale;\n"
858 "uniform myhalf SpecularScale;\n"
859 "uniform myhalf SpecularPower;\n"
861 "#ifdef USEOFFSETMAPPING\n"
862 "vec2 OffsetMapping(vec2 TexCoord)\n"
864 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
865 " // 14 sample relief mapping: linear search and then binary search\n"
866 " // this basically steps forward a small amount repeatedly until it finds\n"
867 " // itself inside solid, then jitters forward and back using decreasing\n"
868 " // amounts to find the impact\n"
869 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
870 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
871 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
872 " vec3 RT = vec3(TexCoord, 1);\n"
873 " OffsetVector *= 0.1;\n"
874 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
875 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
876 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
877 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
878 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
879 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
880 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
881 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
882 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
883 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
884 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
885 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
886 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
887 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
890 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
891 " // this basically moves forward the full distance, and then backs up based\n"
892 " // on height of samples\n"
893 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
894 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
895 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
896 " TexCoord += OffsetVector;\n"
897 " OffsetVector *= 0.333;\n"
898 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
899 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
900 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
901 " return TexCoord;\n"
904 "#endif // USEOFFSETMAPPING\n"
906 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
907 "uniform vec2 ShadowMap_TextureScale;\n"
908 "uniform vec4 ShadowMap_Parameters;\n"
911 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
912 "vec3 GetShadowMapTC2D(vec3 dir)\n"
914 " vec3 adir = abs(dir);\n"
915 "# ifndef USESHADOWMAPVSDCT\n"
919 " if (adir.x > adir.y)\n"
921 " if (adir.x > adir.z) // X\n"
925 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
931 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
936 " if (adir.y > adir.z) // Y\n"
940 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
946 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
950 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
951 " stc.xy += offset * ShadowMap_Parameters.y;\n"
952 " stc.z += ShadowMap_Parameters.z;\n"
953 "# if showshadowmap\n"
954 " stc.xy *= ShadowMap_TextureScale;\n"
958 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
959 " float ma = max(max(adir.x, adir.y), adir.z);\n"
960 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
961 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
962 " stc.z += ShadowMap_Parameters.z;\n"
963 "# if showshadowmap\n"
964 " stc.xy *= ShadowMap_TextureScale;\n"
969 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
971 "#ifdef USESHADOWMAPCUBE\n"
972 "vec4 GetShadowMapTCCube(vec3 dir)\n"
974 " vec3 adir = abs(dir);\n"
975 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
979 "#if !showshadowmap\n"
980 "# ifdef USESHADOWMAPRECT\n"
981 "float ShadowMapCompare(vec3 dir)\n"
983 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
985 "# ifdef USESHADOWSAMPLER\n"
987 "# ifdef USESHADOWMAPPCF\n"
988 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
989 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
991 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
996 "# ifdef USESHADOWMAPPCF\n"
997 "# if USESHADOWMAPPCF > 1\n"
998 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
999 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1000 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1001 " vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
1002 " vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
1003 " vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
1004 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1005 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1007 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1008 " vec2 offset = fract(shadowmaptc.xy);\n"
1009 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1010 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1011 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1012 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1013 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1016 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1024 "# ifdef USESHADOWMAP2D\n"
1025 "float ShadowMapCompare(vec3 dir)\n"
1027 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1030 "# ifdef USESHADOWSAMPLER\n"
1031 "# ifdef USESHADOWMAPPCF\n"
1032 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1033 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1034 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1036 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1039 "# ifdef USESHADOWMAPPCF\n"
1040 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1041 "# ifdef GL_ARB_texture_gather\n"
1042 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1044 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1046 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1047 " center *= ShadowMap_TextureScale;\n"
1048 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1049 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1050 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1051 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1052 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1053 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1054 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1056 "# ifdef GL_EXT_gpu_shader4\n"
1057 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1059 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1061 "# if USESHADOWMAPPCF > 1\n"
1062 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1063 " center *= ShadowMap_TextureScale;\n"
1064 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1065 " vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
1066 " vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
1067 " vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
1068 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1069 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1071 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1072 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1073 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1074 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1075 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1076 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1080 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1087 "# ifdef USESHADOWMAPCUBE\n"
1088 "float ShadowMapCompare(vec3 dir)\n"
1090 " // apply depth texture cubemap as light filter\n"
1091 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1093 "# ifdef USESHADOWSAMPLER\n"
1094 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1096 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1103 "#ifdef MODE_WATER\n"
1108 "#ifdef USEOFFSETMAPPING\n"
1109 " // apply offsetmapping\n"
1110 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1111 "#define TexCoord TexCoordOffset\n"
1114 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1115 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1116 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1117 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1118 " // FIXME temporary hack to detect the case that the reflection\n"
1119 " // gets blackened at edges due to leaving the area that contains actual\n"
1121 " // Remove this 'ack once we have a better way to stop this thing from\n"
1123 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1124 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1125 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1126 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1127 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1128 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1129 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1130 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1131 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1132 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1133 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1134 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1137 "#else // !MODE_WATER\n"
1138 "#ifdef MODE_REFRACTION\n"
1140 "// refraction pass\n"
1143 "#ifdef USEOFFSETMAPPING\n"
1144 " // apply offsetmapping\n"
1145 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1146 "#define TexCoord TexCoordOffset\n"
1149 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1150 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1151 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1152 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1153 " // FIXME temporary hack to detect the case that the reflection\n"
1154 " // gets blackened at edges due to leaving the area that contains actual\n"
1156 " // Remove this 'ack once we have a better way to stop this thing from\n"
1158 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1159 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1160 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1161 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1162 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1163 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1166 "#else // !MODE_REFRACTION\n"
1169 "#ifdef USEOFFSETMAPPING\n"
1170 " // apply offsetmapping\n"
1171 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1172 "#define TexCoord TexCoordOffset\n"
1175 " // combine the diffuse textures (base, pants, shirt)\n"
1176 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1177 "#ifdef USECOLORMAPPING\n"
1178 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1180 "#ifdef USEVERTEXTEXTUREBLEND\n"
1181 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1182 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1183 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1184 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1186 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1189 "#ifdef USEDIFFUSE\n"
1190 " // get the surface normal and the gloss color\n"
1191 "# ifdef USEVERTEXTEXTUREBLEND\n"
1192 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1193 "# ifdef USESPECULAR\n"
1194 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1197 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1198 "# ifdef USESPECULAR\n"
1199 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1206 "#ifdef MODE_LIGHTSOURCE\n"
1207 " // light source\n"
1209 " // calculate surface normal, light normal, and specular normal\n"
1210 " // compute color intensity for the two textures (colormap and glossmap)\n"
1211 " // scale by light color and attenuation as efficiently as possible\n"
1212 " // (do as much scalar math as possible rather than vector math)\n"
1213 "# ifdef USEDIFFUSE\n"
1214 " // get the light normal\n"
1215 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1217 "# ifdef USESPECULAR\n"
1218 "# ifndef USEEXACTSPECULARMATH\n"
1219 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1222 " // calculate directional shading\n"
1223 "# ifdef USEEXACTSPECULARMATH\n"
1224 " 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"
1226 " 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"
1229 "# ifdef USEDIFFUSE\n"
1230 " // calculate directional shading\n"
1231 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1233 " // calculate directionless shading\n"
1234 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1238 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1239 "#if !showshadowmap\n"
1240 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1244 "# ifdef USECUBEFILTER\n"
1245 " // apply light cubemap filter\n"
1246 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1247 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1249 "#endif // MODE_LIGHTSOURCE\n"
1254 "#ifdef MODE_LIGHTDIRECTION\n"
1255 " // directional model lighting\n"
1256 "# ifdef USEDIFFUSE\n"
1257 " // get the light normal\n"
1258 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1260 "# ifdef USESPECULAR\n"
1261 " // calculate directional shading\n"
1262 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1263 "# ifdef USEEXACTSPECULARMATH\n"
1264 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1266 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1267 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1270 "# ifdef USEDIFFUSE\n"
1272 " // calculate directional shading\n"
1273 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1275 " color.rgb *= AmbientColor;\n"
1278 "#endif // MODE_LIGHTDIRECTION\n"
1283 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1284 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1286 " // get the light normal\n"
1287 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1288 " myhalf3 diffusenormal;\n"
1289 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1290 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1291 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1292 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1293 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1294 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1295 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1296 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1297 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1298 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1299 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1300 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1301 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1302 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1303 "# ifdef USESPECULAR\n"
1304 "# ifdef USEEXACTSPECULARMATH\n"
1305 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1307 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1308 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1312 " // apply lightmap color\n"
1313 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1314 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1319 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1320 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1322 " // get the light normal\n"
1323 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1324 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1325 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1326 "# ifdef USESPECULAR\n"
1327 "# ifdef USEEXACTSPECULARMATH\n"
1328 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1330 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1331 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1335 " // apply lightmap color\n"
1336 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1337 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1342 "#ifdef MODE_LIGHTMAP\n"
1343 " // apply lightmap color\n"
1344 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1345 "#endif // MODE_LIGHTMAP\n"
1350 "#ifdef MODE_VERTEXCOLOR\n"
1351 " // apply lightmap color\n"
1352 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1353 "#endif // MODE_VERTEXCOLOR\n"
1358 "#ifdef MODE_FLATCOLOR\n"
1359 "#endif // MODE_FLATCOLOR\n"
1367 " color *= TintColor;\n"
1370 "#ifdef USEVERTEXTEXTUREBLEND\n"
1371 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1373 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1377 " color.rgb *= SceneBrightness;\n"
1379 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1381 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1384 " // 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"
1385 "#ifdef USEREFLECTION\n"
1386 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1387 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1388 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1389 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1390 " // FIXME temporary hack to detect the case that the reflection\n"
1391 " // gets blackened at edges due to leaving the area that contains actual\n"
1393 " // Remove this 'ack once we have a better way to stop this thing from\n"
1395 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1396 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1397 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1398 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1399 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1400 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1403 " gl_FragColor = vec4(color);\n"
1405 "#if showshadowmap\n"
1406 "# ifdef USESHADOWMAPRECT\n"
1407 "# ifdef USESHADOWSAMPLER\n"
1408 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1410 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1413 "# ifdef USESHADOWMAP2D\n"
1414 "# ifdef USESHADOWSAMPLER\n"
1415 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1417 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1421 "# ifdef USESHADOWMAPCUBE\n"
1422 "# ifdef USESHADOWSAMPLER\n"
1423 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1425 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1430 "#endif // !MODE_REFRACTION\n"
1431 "#endif // !MODE_WATER\n"
1433 "#endif // FRAGMENT_SHADER\n"
1435 "#endif // !MODE_GENERIC\n"
1436 "#endif // !MODE_POSTPROCESS\n"
1437 "#endif // !MODE_SHOWDEPTH\n"
1438 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1441 typedef struct shaderpermutationinfo_s
1443 const char *pretext;
1446 shaderpermutationinfo_t;
1448 typedef struct shadermodeinfo_s
1450 const char *vertexfilename;
1451 const char *geometryfilename;
1452 const char *fragmentfilename;
1453 const char *pretext;
1458 typedef enum shaderpermutation_e
1460 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1461 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1462 SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
1463 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1464 SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
1465 SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
1466 SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
1467 SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
1468 SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
1469 SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
1470 SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
1471 SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
1472 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1473 SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1474 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
1475 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1476 SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
1477 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
1478 SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
1479 SHADERPERMUTATION_SHADOWMAPPCF = 1<<14, ///< (lightsource) use percentage closer filtering on shadowmap test results
1480 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<15, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1481 SHADERPERMUTATION_SHADOWSAMPLER = 1<<16, ///< (lightsource) use hardware shadowmap test
1482 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<17, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1483 SHADERPERMUTATION_LIMIT = 1<<18, ///< size of permutations array
1484 SHADERPERMUTATION_COUNT = 18 ///< size of shaderpermutationinfo array
1486 shaderpermutation_t;
1488 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1489 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1491 {"#define USEDIFFUSE\n", " diffuse"},
1492 {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
1493 {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
1494 {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
1495 {"#define USECUBEFILTER\n", " cubefilter"},
1496 {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
1497 {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
1498 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1499 {"#define USEREFLECTION\n", " reflection"},
1500 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1501 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1502 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1503 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1504 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1505 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1506 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1507 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1508 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1511 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1512 typedef enum shadermode_e
1514 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1515 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1516 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1517 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1518 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1519 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1520 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1521 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1522 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1523 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1524 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1525 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1526 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1531 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1532 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1534 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1535 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1536 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1537 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1538 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1539 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1540 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1541 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1542 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1543 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1544 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1545 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1546 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1549 struct r_glsl_permutation_s;
1550 typedef struct r_glsl_permutation_s
1552 /// hash lookup data
1553 struct r_glsl_permutation_s *hashnext;
1555 unsigned int permutation;
1557 /// indicates if we have tried compiling this permutation already
1559 /// 0 if compilation failed
1561 /// locations of detected uniforms in program object, or -1 if not found
1562 int loc_Texture_First;
1563 int loc_Texture_Second;
1564 int loc_Texture_GammaRamps;
1565 int loc_Texture_Normal;
1566 int loc_Texture_Color;
1567 int loc_Texture_Gloss;
1568 int loc_Texture_Glow;
1569 int loc_Texture_SecondaryNormal;
1570 int loc_Texture_SecondaryColor;
1571 int loc_Texture_SecondaryGloss;
1572 int loc_Texture_SecondaryGlow;
1573 int loc_Texture_Pants;
1574 int loc_Texture_Shirt;
1575 int loc_Texture_FogMask;
1576 int loc_Texture_Lightmap;
1577 int loc_Texture_Deluxemap;
1578 int loc_Texture_Attenuation;
1579 int loc_Texture_Cube;
1580 int loc_Texture_Refraction;
1581 int loc_Texture_Reflection;
1582 int loc_Texture_ShadowMapRect;
1583 int loc_Texture_ShadowMapCube;
1584 int loc_Texture_ShadowMap2D;
1585 int loc_Texture_CubeProjection;
1587 int loc_LightPosition;
1588 int loc_EyePosition;
1589 int loc_Color_Pants;
1590 int loc_Color_Shirt;
1591 int loc_FogRangeRecip;
1592 int loc_AmbientScale;
1593 int loc_DiffuseScale;
1594 int loc_SpecularScale;
1595 int loc_SpecularPower;
1597 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1598 int loc_OffsetMapping_Scale;
1600 int loc_AmbientColor;
1601 int loc_DiffuseColor;
1602 int loc_SpecularColor;
1604 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1605 int loc_GammaCoeff; ///< 1 / gamma
1606 int loc_DistortScaleRefractReflect;
1607 int loc_ScreenScaleRefractReflect;
1608 int loc_ScreenCenterRefractReflect;
1609 int loc_RefractColor;
1610 int loc_ReflectColor;
1611 int loc_ReflectFactor;
1612 int loc_ReflectOffset;
1620 int loc_ShadowMap_TextureScale;
1621 int loc_ShadowMap_Parameters;
1623 r_glsl_permutation_t;
1625 #define SHADERPERMUTATION_HASHSIZE 4096
1627 /// information about each possible shader permutation
1628 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1629 /// currently selected permutation
1630 r_glsl_permutation_t *r_glsl_permutation;
1631 /// storage for permutations linked in the hash table
1632 memexpandablearray_t r_glsl_permutationarray;
1634 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1636 //unsigned int hashdepth = 0;
1637 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1638 r_glsl_permutation_t *p;
1639 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1641 if (p->mode == mode && p->permutation == permutation)
1643 //if (hashdepth > 10)
1644 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1649 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1651 p->permutation = permutation;
1652 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1653 r_glsl_permutationhash[mode][hashindex] = p;
1654 //if (hashdepth > 10)
1655 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1659 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1662 if (!filename || !filename[0])
1664 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1667 if (printfromdisknotice)
1668 Con_DPrint("from disk... ");
1669 return shaderstring;
1671 else if (!strcmp(filename, "glsl/default.glsl"))
1673 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1674 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1676 return shaderstring;
1679 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1682 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1683 int vertstrings_count = 0;
1684 int geomstrings_count = 0;
1685 int fragstrings_count = 0;
1686 char *vertexstring, *geometrystring, *fragmentstring;
1687 const char *vertstrings_list[32+3];
1688 const char *geomstrings_list[32+3];
1689 const char *fragstrings_list[32+3];
1690 char permutationname[256];
1697 permutationname[0] = 0;
1698 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1699 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1700 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1702 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1704 // the first pretext is which type of shader to compile as
1705 // (later these will all be bound together as a program object)
1706 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1707 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1708 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1710 // the second pretext is the mode (for example a light source)
1711 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1712 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1713 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1714 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1716 // now add all the permutation pretexts
1717 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1719 if (permutation & (1<<i))
1721 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1722 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1723 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1724 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1728 // keep line numbers correct
1729 vertstrings_list[vertstrings_count++] = "\n";
1730 geomstrings_list[geomstrings_count++] = "\n";
1731 fragstrings_list[fragstrings_count++] = "\n";
1735 // now append the shader text itself
1736 vertstrings_list[vertstrings_count++] = vertexstring;
1737 geomstrings_list[geomstrings_count++] = geometrystring;
1738 fragstrings_list[fragstrings_count++] = fragmentstring;
1740 // if any sources were NULL, clear the respective list
1742 vertstrings_count = 0;
1743 if (!geometrystring)
1744 geomstrings_count = 0;
1745 if (!fragmentstring)
1746 fragstrings_count = 0;
1748 // compile the shader program
1749 if (vertstrings_count + geomstrings_count + fragstrings_count)
1750 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1754 qglUseProgramObjectARB(p->program);CHECKGLERROR
1755 // look up all the uniform variable names we care about, so we don't
1756 // have to look them up every time we set them
1757 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1758 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1759 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1760 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1761 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1762 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1763 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1764 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1765 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1766 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1767 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1768 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1769 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1770 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1771 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1772 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1773 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1774 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1775 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1776 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1777 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1778 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1779 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1780 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1781 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1782 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1783 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1784 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1785 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1786 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1787 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1788 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1789 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1790 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1791 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1792 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1793 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1794 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1795 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1796 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1797 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1798 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1799 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1800 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1801 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1802 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1803 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1804 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1805 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1806 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1807 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1808 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1809 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1810 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1811 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1812 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1813 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1814 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1815 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1816 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1817 // initialize the samplers to refer to the texture units we use
1818 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1819 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1820 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1821 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1822 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1823 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1824 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1825 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1826 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1827 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1828 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1829 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1830 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1831 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1832 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1833 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1834 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1835 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1836 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1837 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1838 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1839 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1840 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1841 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1843 if (developer.integer)
1844 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1847 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1851 Mem_Free(vertexstring);
1853 Mem_Free(geometrystring);
1855 Mem_Free(fragmentstring);
1858 void R_GLSL_Restart_f(void)
1860 unsigned int i, limit;
1861 r_glsl_permutation_t *p;
1862 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1863 for (i = 0;i < limit;i++)
1865 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1867 GL_Backend_FreeProgram(p->program);
1868 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1871 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1874 void R_GLSL_DumpShader_f(void)
1878 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1881 Con_Printf("failed to write to glsl/default.glsl\n");
1885 FS_Print(file, "/* The engine may define the following macros:\n");
1886 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1887 for (i = 0;i < SHADERMODE_COUNT;i++)
1888 FS_Print(file, shadermodeinfo[i].pretext);
1889 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1890 FS_Print(file, shaderpermutationinfo[i].pretext);
1891 FS_Print(file, "*/\n");
1892 FS_Print(file, builtinshaderstring);
1895 Con_Printf("glsl/default.glsl written\n");
1898 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1900 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1901 if (r_glsl_permutation != perm)
1903 r_glsl_permutation = perm;
1904 if (!r_glsl_permutation->program)
1906 if (!r_glsl_permutation->compiled)
1907 R_GLSL_CompilePermutation(perm, mode, permutation);
1908 if (!r_glsl_permutation->program)
1910 // remove features until we find a valid permutation
1912 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1914 // reduce i more quickly whenever it would not remove any bits
1915 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1916 if (!(permutation & j))
1919 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1920 if (!r_glsl_permutation->compiled)
1921 R_GLSL_CompilePermutation(perm, mode, permutation);
1922 if (r_glsl_permutation->program)
1925 if (i >= SHADERPERMUTATION_COUNT)
1927 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");
1928 Cvar_SetValueQuick(&r_glsl, 0);
1929 R_GLSL_Restart_f(); // unload shaders
1930 return; // no bit left to clear
1935 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1939 void R_SetupGenericShader(qboolean usetexture)
1941 if (gl_support_fragment_shader)
1943 if (r_glsl.integer && r_glsl_usegeneric.integer)
1944 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1945 else if (r_glsl_permutation)
1947 r_glsl_permutation = NULL;
1948 qglUseProgramObjectARB(0);CHECKGLERROR
1953 void R_SetupGenericTwoTextureShader(int texturemode)
1955 if (gl_support_fragment_shader)
1957 if (r_glsl.integer && r_glsl_usegeneric.integer)
1958 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))));
1959 else if (r_glsl_permutation)
1961 r_glsl_permutation = NULL;
1962 qglUseProgramObjectARB(0);CHECKGLERROR
1965 if (!r_glsl_permutation)
1967 if (texturemode == GL_DECAL && gl_combine.integer)
1968 texturemode = GL_INTERPOLATE_ARB;
1969 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1973 void R_SetupDepthOrShadowShader(void)
1975 if (gl_support_fragment_shader)
1977 if (r_glsl.integer && r_glsl_usegeneric.integer)
1978 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1979 else if (r_glsl_permutation)
1981 r_glsl_permutation = NULL;
1982 qglUseProgramObjectARB(0);CHECKGLERROR
1987 void R_SetupShowDepthShader(void)
1989 if (gl_support_fragment_shader)
1991 if (r_glsl.integer && r_glsl_usegeneric.integer)
1992 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
1993 else if (r_glsl_permutation)
1995 r_glsl_permutation = NULL;
1996 qglUseProgramObjectARB(0);CHECKGLERROR
2001 extern rtexture_t *r_shadow_attenuationgradienttexture;
2002 extern rtexture_t *r_shadow_attenuation2dtexture;
2003 extern rtexture_t *r_shadow_attenuation3dtexture;
2004 extern qboolean r_shadow_usingshadowmaprect;
2005 extern qboolean r_shadow_usingshadowmapcube;
2006 extern qboolean r_shadow_usingshadowmap2d;
2007 extern float r_shadow_shadowmap_texturescale[2];
2008 extern float r_shadow_shadowmap_parameters[4];
2009 extern qboolean r_shadow_shadowmapvsdct;
2010 extern qboolean r_shadow_shadowmapsampler;
2011 extern int r_shadow_shadowmappcf;
2012 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2014 // select a permutation of the lighting shader appropriate to this
2015 // combination of texture, entity, light source, and fogging, only use the
2016 // minimum features necessary to avoid wasting rendering time in the
2017 // fragment shader on features that are not being used
2018 unsigned int permutation = 0;
2019 unsigned int mode = 0;
2020 // TODO: implement geometry-shader based shadow volumes someday
2021 if (r_glsl_offsetmapping.integer)
2023 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2024 if (r_glsl_offsetmapping_reliefmapping.integer)
2025 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2027 if (rsurfacepass == RSURFPASS_BACKGROUND)
2029 // distorted background
2030 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2031 mode = SHADERMODE_WATER;
2033 mode = SHADERMODE_REFRACTION;
2035 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2038 mode = SHADERMODE_LIGHTSOURCE;
2039 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2040 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2041 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2042 permutation |= SHADERPERMUTATION_CUBEFILTER;
2043 if (diffusescale > 0)
2044 permutation |= SHADERPERMUTATION_DIFFUSE;
2045 if (specularscale > 0)
2046 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2047 if (r_refdef.fogenabled)
2048 permutation |= SHADERPERMUTATION_FOG;
2049 if (rsurface.texture->colormapping)
2050 permutation |= SHADERPERMUTATION_COLORMAPPING;
2051 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2053 if (r_shadow_usingshadowmaprect)
2054 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2055 if (r_shadow_usingshadowmap2d)
2056 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2057 if (r_shadow_usingshadowmapcube)
2058 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2059 else if(r_shadow_shadowmapvsdct)
2060 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2062 if (r_shadow_shadowmapsampler)
2063 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2064 if (r_shadow_shadowmappcf > 1)
2065 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2066 else if (r_shadow_shadowmappcf)
2067 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2070 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2072 // unshaded geometry (fullbright or ambient model lighting)
2073 mode = SHADERMODE_FLATCOLOR;
2074 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2075 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2076 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2077 permutation |= SHADERPERMUTATION_GLOW;
2078 if (r_refdef.fogenabled)
2079 permutation |= SHADERPERMUTATION_FOG;
2080 if (rsurface.texture->colormapping)
2081 permutation |= SHADERPERMUTATION_COLORMAPPING;
2082 if (r_glsl_offsetmapping.integer)
2084 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2085 if (r_glsl_offsetmapping_reliefmapping.integer)
2086 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2088 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2089 permutation |= SHADERPERMUTATION_REFLECTION;
2091 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2093 // directional model lighting
2094 mode = SHADERMODE_LIGHTDIRECTION;
2095 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2096 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2097 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2098 permutation |= SHADERPERMUTATION_GLOW;
2099 permutation |= SHADERPERMUTATION_DIFFUSE;
2100 if (specularscale > 0)
2101 permutation |= SHADERPERMUTATION_SPECULAR;
2102 if (r_refdef.fogenabled)
2103 permutation |= SHADERPERMUTATION_FOG;
2104 if (rsurface.texture->colormapping)
2105 permutation |= SHADERPERMUTATION_COLORMAPPING;
2106 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2107 permutation |= SHADERPERMUTATION_REFLECTION;
2109 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2111 // ambient model lighting
2112 mode = SHADERMODE_LIGHTDIRECTION;
2113 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2114 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2115 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2116 permutation |= SHADERPERMUTATION_GLOW;
2117 if (r_refdef.fogenabled)
2118 permutation |= SHADERPERMUTATION_FOG;
2119 if (rsurface.texture->colormapping)
2120 permutation |= SHADERPERMUTATION_COLORMAPPING;
2121 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2122 permutation |= SHADERPERMUTATION_REFLECTION;
2127 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2129 // deluxemapping (light direction texture)
2130 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2131 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2133 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2134 permutation |= SHADERPERMUTATION_DIFFUSE;
2135 if (specularscale > 0)
2136 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2138 else if (r_glsl_deluxemapping.integer >= 2)
2140 // fake deluxemapping (uniform light direction in tangentspace)
2141 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2142 permutation |= SHADERPERMUTATION_DIFFUSE;
2143 if (specularscale > 0)
2144 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2146 else if (rsurface.uselightmaptexture)
2148 // ordinary lightmapping (q1bsp, q3bsp)
2149 mode = SHADERMODE_LIGHTMAP;
2153 // ordinary vertex coloring (q3bsp)
2154 mode = SHADERMODE_VERTEXCOLOR;
2156 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2157 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2158 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2159 permutation |= SHADERPERMUTATION_GLOW;
2160 if (r_refdef.fogenabled)
2161 permutation |= SHADERPERMUTATION_FOG;
2162 if (rsurface.texture->colormapping)
2163 permutation |= SHADERPERMUTATION_COLORMAPPING;
2164 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2165 permutation |= SHADERPERMUTATION_REFLECTION;
2167 if(permutation & SHADERPERMUTATION_SPECULAR)
2168 if(r_shadow_glossexact.integer)
2169 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2170 R_SetupShader_SetPermutation(mode, permutation);
2171 if (mode == SHADERMODE_LIGHTSOURCE)
2173 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2174 if (permutation & SHADERPERMUTATION_DIFFUSE)
2176 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2177 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2178 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2179 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2183 // ambient only is simpler
2184 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]);
2185 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2186 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2187 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2189 // additive passes are only darkened by fog, not tinted
2190 if (r_glsl_permutation->loc_FogColor >= 0)
2191 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2192 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]);
2193 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]);
2197 if (mode == SHADERMODE_LIGHTDIRECTION)
2199 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);
2200 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);
2201 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);
2202 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]);
2206 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2207 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2208 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2210 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]);
2211 if (r_glsl_permutation->loc_GlowColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_GlowColor, rsurface.glowmod[0] * r_hdr_glowintensity.value, rsurface.glowmod[1] * r_hdr_glowintensity.value, rsurface.glowmod[2] * r_hdr_glowintensity.value);
2212 // additive passes are only darkened by fog, not tinted
2213 if (r_glsl_permutation->loc_FogColor >= 0)
2215 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2216 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2218 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2220 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);
2221 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]);
2222 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]);
2223 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2224 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2225 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2226 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2228 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2229 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2230 if (r_glsl_permutation->loc_Color_Pants >= 0)
2232 if (rsurface.texture->currentskinframe->pants)
2233 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2235 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2237 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2239 if (rsurface.texture->currentskinframe->shirt)
2240 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2242 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2244 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2245 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2247 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2251 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2253 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2257 #define SKINFRAME_HASH 1024
2261 int loadsequence; // incremented each level change
2262 memexpandablearray_t array;
2263 skinframe_t *hash[SKINFRAME_HASH];
2266 r_skinframe_t r_skinframe;
2268 void R_SkinFrame_PrepareForPurge(void)
2270 r_skinframe.loadsequence++;
2271 // wrap it without hitting zero
2272 if (r_skinframe.loadsequence >= 200)
2273 r_skinframe.loadsequence = 1;
2276 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2280 // mark the skinframe as used for the purging code
2281 skinframe->loadsequence = r_skinframe.loadsequence;
2284 void R_SkinFrame_Purge(void)
2288 for (i = 0;i < SKINFRAME_HASH;i++)
2290 for (s = r_skinframe.hash[i];s;s = s->next)
2292 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2294 if (s->merged == s->base)
2296 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2297 R_PurgeTexture(s->stain );s->stain = NULL;
2298 R_PurgeTexture(s->merged);s->merged = NULL;
2299 R_PurgeTexture(s->base );s->base = NULL;
2300 R_PurgeTexture(s->pants );s->pants = NULL;
2301 R_PurgeTexture(s->shirt );s->shirt = NULL;
2302 R_PurgeTexture(s->nmap );s->nmap = NULL;
2303 R_PurgeTexture(s->gloss );s->gloss = NULL;
2304 R_PurgeTexture(s->glow );s->glow = NULL;
2305 R_PurgeTexture(s->fog );s->fog = NULL;
2306 s->loadsequence = 0;
2312 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2314 char basename[MAX_QPATH];
2316 Image_StripImageExtension(name, basename, sizeof(basename));
2318 if( last == NULL ) {
2320 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2321 item = r_skinframe.hash[hashindex];
2326 // linearly search through the hash bucket
2327 for( ; item ; item = item->next ) {
2328 if( !strcmp( item->basename, basename ) ) {
2335 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2339 char basename[MAX_QPATH];
2341 Image_StripImageExtension(name, basename, sizeof(basename));
2343 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2344 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2345 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2349 rtexture_t *dyntexture;
2350 // check whether its a dynamic texture
2351 dyntexture = CL_GetDynTexture( basename );
2352 if (!add && !dyntexture)
2354 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2355 memset(item, 0, sizeof(*item));
2356 strlcpy(item->basename, basename, sizeof(item->basename));
2357 item->base = dyntexture; // either NULL or dyntexture handle
2358 item->textureflags = textureflags;
2359 item->comparewidth = comparewidth;
2360 item->compareheight = compareheight;
2361 item->comparecrc = comparecrc;
2362 item->next = r_skinframe.hash[hashindex];
2363 r_skinframe.hash[hashindex] = item;
2365 else if( item->base == NULL )
2367 rtexture_t *dyntexture;
2368 // check whether its a dynamic texture
2369 // 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]
2370 dyntexture = CL_GetDynTexture( basename );
2371 item->base = dyntexture; // either NULL or dyntexture handle
2374 R_SkinFrame_MarkUsed(item);
2378 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2380 unsigned long long avgcolor[5], wsum; \
2388 for(pix = 0; pix < cnt; ++pix) \
2391 for(comp = 0; comp < 3; ++comp) \
2393 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2396 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2398 for(comp = 0; comp < 3; ++comp) \
2399 avgcolor[comp] += getpixel * w; \
2402 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2403 avgcolor[4] += getpixel; \
2405 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2407 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2408 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2409 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2410 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2413 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2415 // FIXME: it should be possible to disable loading various layers using
2416 // cvars, to prevent wasted loading time and memory usage if the user does
2418 qboolean loadnormalmap = true;
2419 qboolean loadgloss = true;
2420 qboolean loadpantsandshirt = true;
2421 qboolean loadglow = true;
2423 unsigned char *pixels;
2424 unsigned char *bumppixels;
2425 unsigned char *basepixels = NULL;
2426 int basepixels_width;
2427 int basepixels_height;
2428 skinframe_t *skinframe;
2433 if (cls.state == ca_dedicated)
2436 // return an existing skinframe if already loaded
2437 // if loading of the first image fails, don't make a new skinframe as it
2438 // would cause all future lookups of this to be missing
2439 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2440 if (skinframe && skinframe->base)
2443 basepixels = loadimagepixelsbgra(name, complain, true);
2444 if (basepixels == NULL)
2447 if (developer_loading.integer)
2448 Con_Printf("loading skin \"%s\"\n", name);
2450 // we've got some pixels to store, so really allocate this new texture now
2452 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2453 skinframe->stain = NULL;
2454 skinframe->merged = NULL;
2455 skinframe->base = r_texture_notexture;
2456 skinframe->pants = NULL;
2457 skinframe->shirt = NULL;
2458 skinframe->nmap = r_texture_blanknormalmap;
2459 skinframe->gloss = NULL;
2460 skinframe->glow = NULL;
2461 skinframe->fog = NULL;
2463 basepixels_width = image_width;
2464 basepixels_height = image_height;
2465 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);
2467 if (textureflags & TEXF_ALPHA)
2469 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2470 if (basepixels[j] < 255)
2472 if (j < basepixels_width * basepixels_height * 4)
2474 // has transparent pixels
2477 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2478 for (j = 0;j < image_width * image_height * 4;j += 4)
2483 pixels[j+3] = basepixels[j+3];
2485 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);
2490 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2491 //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]);
2493 // _norm is the name used by tenebrae and has been adopted as standard
2496 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2498 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);
2502 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2504 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2505 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2506 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);
2508 Mem_Free(bumppixels);
2510 else if (r_shadow_bumpscale_basetexture.value > 0)
2512 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2513 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2514 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);
2518 // _luma is supported for tenebrae compatibility
2519 // (I think it's a very stupid name, but oh well)
2520 // _glow is the preferred name
2521 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;}
2522 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;}
2523 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;}
2524 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;}
2527 Mem_Free(basepixels);
2532 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2534 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL);
2537 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)
2542 for (i = 0;i < width*height;i++)
2543 if (((unsigned char *)&palette[in[i]])[3] > 0)
2545 if (i == width*height)
2548 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2551 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2552 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2555 unsigned char *temp1, *temp2;
2556 skinframe_t *skinframe;
2558 if (cls.state == ca_dedicated)
2561 // if already loaded just return it, otherwise make a new skinframe
2562 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2563 if (skinframe && skinframe->base)
2566 skinframe->stain = NULL;
2567 skinframe->merged = NULL;
2568 skinframe->base = r_texture_notexture;
2569 skinframe->pants = NULL;
2570 skinframe->shirt = NULL;
2571 skinframe->nmap = r_texture_blanknormalmap;
2572 skinframe->gloss = NULL;
2573 skinframe->glow = NULL;
2574 skinframe->fog = NULL;
2576 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2580 if (developer_loading.integer)
2581 Con_Printf("loading 32bit skin \"%s\"\n", name);
2583 if (r_shadow_bumpscale_basetexture.value > 0)
2585 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2586 temp2 = temp1 + width * height * 4;
2587 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2588 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2591 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2592 if (textureflags & TEXF_ALPHA)
2594 for (i = 3;i < width * height * 4;i += 4)
2595 if (skindata[i] < 255)
2597 if (i < width * height * 4)
2599 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2600 memcpy(fogpixels, skindata, width * height * 4);
2601 for (i = 0;i < width * height * 4;i += 4)
2602 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2603 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2604 Mem_Free(fogpixels);
2608 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2609 //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]);
2614 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2617 unsigned char *temp1, *temp2;
2618 unsigned int *palette;
2619 skinframe_t *skinframe;
2621 if (cls.state == ca_dedicated)
2624 // if already loaded just return it, otherwise make a new skinframe
2625 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2626 if (skinframe && skinframe->base)
2629 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2631 skinframe->stain = NULL;
2632 skinframe->merged = NULL;
2633 skinframe->base = r_texture_notexture;
2634 skinframe->pants = NULL;
2635 skinframe->shirt = NULL;
2636 skinframe->nmap = r_texture_blanknormalmap;
2637 skinframe->gloss = NULL;
2638 skinframe->glow = NULL;
2639 skinframe->fog = NULL;
2641 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2645 if (developer_loading.integer)
2646 Con_Printf("loading quake skin \"%s\"\n", name);
2648 if (r_shadow_bumpscale_basetexture.value > 0)
2650 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2651 temp2 = temp1 + width * height * 4;
2652 // use either a custom palette or the quake palette
2653 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2654 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2655 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2658 // use either a custom palette, or the quake palette
2659 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2660 if (loadglowtexture)
2661 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2662 if (loadpantsandshirt)
2664 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2665 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2667 if (skinframe->pants || skinframe->shirt)
2668 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
2669 if (textureflags & TEXF_ALPHA)
2671 for (i = 0;i < width * height;i++)
2672 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2674 if (i < width * height)
2675 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2678 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2679 //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]);
2684 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
2687 skinframe_t *skinframe;
2689 if (cls.state == ca_dedicated)
2692 // if already loaded just return it, otherwise make a new skinframe
2693 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2694 if (skinframe && skinframe->base)
2697 skinframe->stain = NULL;
2698 skinframe->merged = NULL;
2699 skinframe->base = r_texture_notexture;
2700 skinframe->pants = NULL;
2701 skinframe->shirt = NULL;
2702 skinframe->nmap = r_texture_blanknormalmap;
2703 skinframe->gloss = NULL;
2704 skinframe->glow = NULL;
2705 skinframe->fog = NULL;
2707 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2711 if (developer_loading.integer)
2712 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2714 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, skinframe->basename, palette, skinframe->textureflags, true);
2715 if (textureflags & TEXF_ALPHA)
2717 for (i = 0;i < width * height;i++)
2718 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
2720 if (i < width * height)
2721 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
2724 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2725 //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]);
2730 skinframe_t *R_SkinFrame_LoadMissing(void)
2732 skinframe_t *skinframe;
2734 if (cls.state == ca_dedicated)
2737 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2738 skinframe->stain = NULL;
2739 skinframe->merged = NULL;
2740 skinframe->base = r_texture_notexture;
2741 skinframe->pants = NULL;
2742 skinframe->shirt = NULL;
2743 skinframe->nmap = r_texture_blanknormalmap;
2744 skinframe->gloss = NULL;
2745 skinframe->glow = NULL;
2746 skinframe->fog = NULL;
2748 skinframe->avgcolor[0] = rand() / RAND_MAX;
2749 skinframe->avgcolor[1] = rand() / RAND_MAX;
2750 skinframe->avgcolor[2] = rand() / RAND_MAX;
2751 skinframe->avgcolor[3] = 1;
2756 void gl_main_start(void)
2760 memset(r_queries, 0, sizeof(r_queries));
2762 r_qwskincache = NULL;
2763 r_qwskincache_size = 0;
2765 // set up r_skinframe loading system for textures
2766 memset(&r_skinframe, 0, sizeof(r_skinframe));
2767 r_skinframe.loadsequence = 1;
2768 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2770 r_main_texturepool = R_AllocTexturePool();
2771 R_BuildBlankTextures();
2773 if (gl_texturecubemap)
2776 R_BuildNormalizationCube();
2778 r_texture_fogattenuation = NULL;
2779 r_texture_gammaramps = NULL;
2780 //r_texture_fogintensity = NULL;
2781 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2782 memset(&r_waterstate, 0, sizeof(r_waterstate));
2783 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2784 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2785 memset(&r_svbsp, 0, sizeof (r_svbsp));
2787 r_refdef.fogmasktable_density = 0;
2790 extern rtexture_t *loadingscreentexture;
2791 void gl_main_shutdown(void)
2794 qglDeleteQueriesARB(r_maxqueries, r_queries);
2798 memset(r_queries, 0, sizeof(r_queries));
2800 r_qwskincache = NULL;
2801 r_qwskincache_size = 0;
2803 // clear out the r_skinframe state
2804 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2805 memset(&r_skinframe, 0, sizeof(r_skinframe));
2808 Mem_Free(r_svbsp.nodes);
2809 memset(&r_svbsp, 0, sizeof (r_svbsp));
2810 R_FreeTexturePool(&r_main_texturepool);
2811 loadingscreentexture = NULL;
2812 r_texture_blanknormalmap = NULL;
2813 r_texture_white = NULL;
2814 r_texture_grey128 = NULL;
2815 r_texture_black = NULL;
2816 r_texture_whitecube = NULL;
2817 r_texture_normalizationcube = NULL;
2818 r_texture_fogattenuation = NULL;
2819 r_texture_gammaramps = NULL;
2820 //r_texture_fogintensity = NULL;
2821 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2822 memset(&r_waterstate, 0, sizeof(r_waterstate));
2826 extern void CL_ParseEntityLump(char *entitystring);
2827 void gl_main_newmap(void)
2829 // FIXME: move this code to client
2831 char *entities, entname[MAX_QPATH];
2833 Mem_Free(r_qwskincache);
2834 r_qwskincache = NULL;
2835 r_qwskincache_size = 0;
2838 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2839 l = (int)strlen(entname) - 4;
2840 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2842 memcpy(entname + l, ".ent", 5);
2843 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2845 CL_ParseEntityLump(entities);
2850 if (cl.worldmodel->brush.entities)
2851 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2855 void GL_Main_Init(void)
2857 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2859 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2860 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2861 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2862 if (gamemode == GAME_NEHAHRA)
2864 Cvar_RegisterVariable (&gl_fogenable);
2865 Cvar_RegisterVariable (&gl_fogdensity);
2866 Cvar_RegisterVariable (&gl_fogred);
2867 Cvar_RegisterVariable (&gl_foggreen);
2868 Cvar_RegisterVariable (&gl_fogblue);
2869 Cvar_RegisterVariable (&gl_fogstart);
2870 Cvar_RegisterVariable (&gl_fogend);
2871 Cvar_RegisterVariable (&gl_skyclip);
2873 Cvar_RegisterVariable(&r_motionblur);
2874 Cvar_RegisterVariable(&r_motionblur_maxblur);
2875 Cvar_RegisterVariable(&r_motionblur_bmin);
2876 Cvar_RegisterVariable(&r_motionblur_vmin);
2877 Cvar_RegisterVariable(&r_motionblur_vmax);
2878 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2879 Cvar_RegisterVariable(&r_motionblur_randomize);
2880 Cvar_RegisterVariable(&r_damageblur);
2881 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
2882 Cvar_RegisterVariable(&r_equalize_entities_minambient);
2883 Cvar_RegisterVariable(&r_equalize_entities_by);
2884 Cvar_RegisterVariable(&r_equalize_entities_to);
2885 Cvar_RegisterVariable(&r_animcache);
2886 Cvar_RegisterVariable(&r_depthfirst);
2887 Cvar_RegisterVariable(&r_useinfinitefarclip);
2888 Cvar_RegisterVariable(&r_nearclip);
2889 Cvar_RegisterVariable(&r_showbboxes);
2890 Cvar_RegisterVariable(&r_showsurfaces);
2891 Cvar_RegisterVariable(&r_showtris);
2892 Cvar_RegisterVariable(&r_shownormals);
2893 Cvar_RegisterVariable(&r_showlighting);
2894 Cvar_RegisterVariable(&r_showshadowvolumes);
2895 Cvar_RegisterVariable(&r_showcollisionbrushes);
2896 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2897 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2898 Cvar_RegisterVariable(&r_showdisabledepthtest);
2899 Cvar_RegisterVariable(&r_drawportals);
2900 Cvar_RegisterVariable(&r_drawentities);
2901 Cvar_RegisterVariable(&r_cullentities_trace);
2902 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2903 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2904 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2905 Cvar_RegisterVariable(&r_drawviewmodel);
2906 Cvar_RegisterVariable(&r_speeds);
2907 Cvar_RegisterVariable(&r_fullbrights);
2908 Cvar_RegisterVariable(&r_wateralpha);
2909 Cvar_RegisterVariable(&r_dynamic);
2910 Cvar_RegisterVariable(&r_fullbright);
2911 Cvar_RegisterVariable(&r_shadows);
2912 Cvar_RegisterVariable(&r_shadows_darken);
2913 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
2914 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2915 Cvar_RegisterVariable(&r_shadows_throwdistance);
2916 Cvar_RegisterVariable(&r_shadows_throwdirection);
2917 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2918 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2919 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2920 Cvar_RegisterVariable(&r_fog_exp2);
2921 Cvar_RegisterVariable(&r_drawfog);
2922 Cvar_RegisterVariable(&r_textureunits);
2923 Cvar_RegisterVariable(&r_glsl);
2924 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2925 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2926 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2927 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2928 Cvar_RegisterVariable(&r_glsl_postprocess);
2929 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2930 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2931 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2932 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2933 Cvar_RegisterVariable(&r_glsl_usegeneric);
2934 Cvar_RegisterVariable(&r_water);
2935 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2936 Cvar_RegisterVariable(&r_water_clippingplanebias);
2937 Cvar_RegisterVariable(&r_water_refractdistort);
2938 Cvar_RegisterVariable(&r_water_reflectdistort);
2939 Cvar_RegisterVariable(&r_lerpsprites);
2940 Cvar_RegisterVariable(&r_lerpmodels);
2941 Cvar_RegisterVariable(&r_lerplightstyles);
2942 Cvar_RegisterVariable(&r_waterscroll);
2943 Cvar_RegisterVariable(&r_bloom);
2944 Cvar_RegisterVariable(&r_bloom_colorscale);
2945 Cvar_RegisterVariable(&r_bloom_brighten);
2946 Cvar_RegisterVariable(&r_bloom_blur);
2947 Cvar_RegisterVariable(&r_bloom_resolution);
2948 Cvar_RegisterVariable(&r_bloom_colorexponent);
2949 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2950 Cvar_RegisterVariable(&r_hdr);
2951 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2952 Cvar_RegisterVariable(&r_hdr_glowintensity);
2953 Cvar_RegisterVariable(&r_hdr_range);
2954 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2955 Cvar_RegisterVariable(&developer_texturelogging);
2956 Cvar_RegisterVariable(&gl_lightmaps);
2957 Cvar_RegisterVariable(&r_test);
2958 Cvar_RegisterVariable(&r_batchmode);
2959 Cvar_RegisterVariable(&r_glsl_saturation);
2960 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2961 Cvar_SetValue("r_fullbrights", 0);
2962 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2964 Cvar_RegisterVariable(&r_track_sprites);
2965 Cvar_RegisterVariable(&r_track_sprites_flags);
2966 Cvar_RegisterVariable(&r_track_sprites_scalew);
2967 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2970 extern void R_Textures_Init(void);
2971 extern void GL_Draw_Init(void);
2972 extern void GL_Main_Init(void);
2973 extern void R_Shadow_Init(void);
2974 extern void R_Sky_Init(void);
2975 extern void GL_Surf_Init(void);
2976 extern void R_Particles_Init(void);
2977 extern void R_Explosion_Init(void);
2978 extern void gl_backend_init(void);
2979 extern void Sbar_Init(void);
2980 extern void R_LightningBeams_Init(void);
2981 extern void Mod_RenderInit(void);
2983 void Render_Init(void)
2995 R_LightningBeams_Init();
3004 extern char *ENGINE_EXTENSIONS;
3007 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3008 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3009 gl_version = (const char *)qglGetString(GL_VERSION);
3010 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3014 if (!gl_platformextensions)
3015 gl_platformextensions = "";
3017 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3018 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3019 Con_Printf("GL_VERSION: %s\n", gl_version);
3020 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3021 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3023 VID_CheckExtensions();
3025 // LordHavoc: report supported extensions
3026 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3028 // clear to black (loading plaque will be seen over this)
3030 qglClearColor(0,0,0,1);CHECKGLERROR
3031 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3034 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3038 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3040 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3043 p = r_refdef.view.frustum + i;
3048 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3052 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3056 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3060 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3064 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3068 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3072 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3076 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3084 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3088 for (i = 0;i < numplanes;i++)
3095 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3099 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3103 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3107 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3111 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3115 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3119 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3123 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3131 //==================================================================================
3133 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3136 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3137 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3138 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3141 typedef struct r_animcache_entity_s
3148 qboolean wantnormals;
3149 qboolean wanttangents;
3151 r_animcache_entity_t;
3153 typedef struct r_animcache_s
3155 r_animcache_entity_t entity[MAX_EDICTS*2];
3161 static r_animcache_t r_animcachestate;
3163 void R_AnimCache_Free(void)
3166 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3168 r_animcachestate.entity[idx].maxvertices = 0;
3169 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3170 r_animcachestate.entity[idx].vertex3f = NULL;
3171 r_animcachestate.entity[idx].normal3f = NULL;
3172 r_animcachestate.entity[idx].svector3f = NULL;
3173 r_animcachestate.entity[idx].tvector3f = NULL;
3175 r_animcachestate.currentindex = 0;
3176 r_animcachestate.maxindex = 0;
3179 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3183 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3185 if (cache->maxvertices >= numvertices)
3188 // Release existing memory
3189 if (cache->vertex3f)
3190 Mem_Free(cache->vertex3f);
3192 // Pad by 1024 verts
3193 cache->maxvertices = (numvertices + 1023) & ~1023;
3194 arraySize = cache->maxvertices * 3;
3196 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3197 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3198 r_animcachestate.entity[cacheIdx].vertex3f = base;
3199 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3200 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3201 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3203 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3206 void R_AnimCache_NewFrame(void)
3210 if (r_animcache.integer && r_drawentities.integer)
3211 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3212 else if (r_animcachestate.maxindex)
3215 r_animcachestate.currentindex = 0;
3217 for (i = 0;i < r_refdef.scene.numentities;i++)
3218 r_refdef.scene.entities[i]->animcacheindex = -1;
3221 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3223 dp_model_t *model = ent->model;
3224 r_animcache_entity_t *c;
3225 // see if it's already cached this frame
3226 if (ent->animcacheindex >= 0)
3228 // add normals/tangents if needed
3229 c = r_animcachestate.entity + ent->animcacheindex;
3231 wantnormals = false;
3232 if (c->wanttangents)
3233 wanttangents = false;
3234 if (wantnormals || wanttangents)
3235 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3239 // see if this ent is worth caching
3240 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3242 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3244 // assign it a cache entry and make sure the arrays are big enough
3245 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3246 ent->animcacheindex = r_animcachestate.currentindex++;
3247 c = r_animcachestate.entity + ent->animcacheindex;
3248 c->wantnormals = wantnormals;
3249 c->wanttangents = wanttangents;
3250 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3255 void R_AnimCache_CacheVisibleEntities(void)
3258 qboolean wantnormals;
3259 qboolean wanttangents;
3261 if (!r_animcachestate.maxindex)
3264 wantnormals = !r_showsurfaces.integer;
3265 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3267 // TODO: thread this?
3269 for (i = 0;i < r_refdef.scene.numentities;i++)
3271 if (!r_refdef.viewcache.entityvisible[i])
3273 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3277 //==================================================================================
3279 static void R_View_UpdateEntityLighting (void)
3282 entity_render_t *ent;
3283 vec3_t tempdiffusenormal, avg;
3284 vec_t f, fa, fd, fdd;
3286 for (i = 0;i < r_refdef.scene.numentities;i++)
3288 ent = r_refdef.scene.entities[i];
3290 // skip unseen models
3291 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3295 if (ent->model && ent->model->brush.num_leafs)
3297 // TODO: use modellight for r_ambient settings on world?
3298 VectorSet(ent->modellight_ambient, 0, 0, 0);
3299 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3300 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3304 // fetch the lighting from the worldmodel data
3305 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));
3306 VectorClear(ent->modellight_diffuse);
3307 VectorClear(tempdiffusenormal);
3308 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3311 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3312 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3313 if(ent->flags & RENDER_EQUALIZE)
3315 // first fix up ambient lighting...
3316 if(r_equalize_entities_minambient.value > 0)
3318 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3321 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3322 if(fa < r_equalize_entities_minambient.value * fd)
3325 // fa'/fd' = minambient
3326 // fa'+0.25*fd' = fa+0.25*fd
3328 // fa' = fd' * minambient
3329 // fd'*(0.25+minambient) = fa+0.25*fd
3331 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3332 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3334 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3335 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
3336 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3337 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3342 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3344 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3345 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3348 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3349 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3350 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3356 VectorSet(ent->modellight_ambient, 1, 1, 1);
3358 // move the light direction into modelspace coordinates for lighting code
3359 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3360 if(VectorLength2(ent->modellight_lightdir) == 0)
3361 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3362 VectorNormalize(ent->modellight_lightdir);
3366 #define MAX_LINEOFSIGHTTRACES 64
3368 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3371 vec3_t boxmins, boxmaxs;
3374 dp_model_t *model = r_refdef.scene.worldmodel;
3376 if (!model || !model->brush.TraceLineOfSight)
3379 // expand the box a little
3380 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3381 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3382 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3383 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3384 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3385 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3388 VectorCopy(eye, start);
3389 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3390 if (model->brush.TraceLineOfSight(model, start, end))
3393 // try various random positions
3394 for (i = 0;i < numsamples;i++)
3396 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3397 if (model->brush.TraceLineOfSight(model, start, end))
3405 static void R_View_UpdateEntityVisible (void)
3408 entity_render_t *ent;
3410 if (!r_drawentities.integer)
3413 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3414 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3416 // worldmodel can check visibility
3417 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3418 for (i = 0;i < r_refdef.scene.numentities;i++)
3420 ent = r_refdef.scene.entities[i];
3421 if (!(ent->flags & renderimask))
3422 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)))
3423 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
3424 r_refdef.viewcache.entityvisible[i] = true;
3426 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3428 for (i = 0;i < r_refdef.scene.numentities;i++)
3430 ent = r_refdef.scene.entities[i];
3431 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3433 if(R_CanSeeBox(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3434 ent->last_trace_visibility = realtime;
3435 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3436 r_refdef.viewcache.entityvisible[i] = 0;
3443 // no worldmodel or it can't check visibility
3444 for (i = 0;i < r_refdef.scene.numentities;i++)
3446 ent = r_refdef.scene.entities[i];
3447 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));
3452 /// only used if skyrendermasked, and normally returns false
3453 int R_DrawBrushModelsSky (void)
3456 entity_render_t *ent;
3458 if (!r_drawentities.integer)
3462 for (i = 0;i < r_refdef.scene.numentities;i++)
3464 if (!r_refdef.viewcache.entityvisible[i])
3466 ent = r_refdef.scene.entities[i];
3467 if (!ent->model || !ent->model->DrawSky)
3469 ent->model->DrawSky(ent);
3475 static void R_DrawNoModel(entity_render_t *ent);
3476 static void R_DrawModels(void)
3479 entity_render_t *ent;
3481 if (!r_drawentities.integer)
3484 for (i = 0;i < r_refdef.scene.numentities;i++)
3486 if (!r_refdef.viewcache.entityvisible[i])
3488 ent = r_refdef.scene.entities[i];
3489 r_refdef.stats.entities++;
3490 if (ent->model && ent->model->Draw != NULL)
3491 ent->model->Draw(ent);
3497 static void R_DrawModelsDepth(void)
3500 entity_render_t *ent;
3502 if (!r_drawentities.integer)
3505 for (i = 0;i < r_refdef.scene.numentities;i++)
3507 if (!r_refdef.viewcache.entityvisible[i])
3509 ent = r_refdef.scene.entities[i];
3510 if (ent->model && ent->model->DrawDepth != NULL)
3511 ent->model->DrawDepth(ent);
3515 static void R_DrawModelsDebug(void)
3518 entity_render_t *ent;
3520 if (!r_drawentities.integer)
3523 for (i = 0;i < r_refdef.scene.numentities;i++)
3525 if (!r_refdef.viewcache.entityvisible[i])
3527 ent = r_refdef.scene.entities[i];
3528 if (ent->model && ent->model->DrawDebug != NULL)
3529 ent->model->DrawDebug(ent);
3533 static void R_DrawModelsAddWaterPlanes(void)
3536 entity_render_t *ent;
3538 if (!r_drawentities.integer)
3541 for (i = 0;i < r_refdef.scene.numentities;i++)
3543 if (!r_refdef.viewcache.entityvisible[i])
3545 ent = r_refdef.scene.entities[i];
3546 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3547 ent->model->DrawAddWaterPlanes(ent);
3551 static void R_View_SetFrustum(void)
3554 double slopex, slopey;
3555 vec3_t forward, left, up, origin;
3557 // we can't trust r_refdef.view.forward and friends in reflected scenes
3558 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3561 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3562 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3563 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3564 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3565 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3566 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3567 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3568 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3569 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3570 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3571 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3572 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3576 zNear = r_refdef.nearclip;
3577 nudge = 1.0 - 1.0 / (1<<23);
3578 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3579 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3580 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3581 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3582 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3583 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3584 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3585 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3591 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3592 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3593 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3594 r_refdef.view.frustum[0].dist = m[15] - m[12];
3596 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3597 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3598 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3599 r_refdef.view.frustum[1].dist = m[15] + m[12];
3601 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3602 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3603 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3604 r_refdef.view.frustum[2].dist = m[15] - m[13];
3606 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3607 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3608 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3609 r_refdef.view.frustum[3].dist = m[15] + m[13];
3611 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3612 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3613 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3614 r_refdef.view.frustum[4].dist = m[15] - m[14];
3616 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3617 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3618 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3619 r_refdef.view.frustum[5].dist = m[15] + m[14];
3622 if (r_refdef.view.useperspective)
3624 slopex = 1.0 / r_refdef.view.frustum_x;
3625 slopey = 1.0 / r_refdef.view.frustum_y;
3626 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3627 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3628 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3629 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3630 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3632 // Leaving those out was a mistake, those were in the old code, and they
3633 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3634 // I couldn't reproduce it after adding those normalizations. --blub
3635 VectorNormalize(r_refdef.view.frustum[0].normal);
3636 VectorNormalize(r_refdef.view.frustum[1].normal);
3637 VectorNormalize(r_refdef.view.frustum[2].normal);
3638 VectorNormalize(r_refdef.view.frustum[3].normal);
3640 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3641 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]);
3642 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]);
3643 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]);
3644 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]);
3646 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3647 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3648 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3649 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3650 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3654 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3655 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3656 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3657 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3658 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3659 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3660 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3661 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3662 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3663 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3665 r_refdef.view.numfrustumplanes = 5;
3667 if (r_refdef.view.useclipplane)
3669 r_refdef.view.numfrustumplanes = 6;
3670 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3673 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3674 PlaneClassify(r_refdef.view.frustum + i);
3676 // LordHavoc: note to all quake engine coders, Quake had a special case
3677 // for 90 degrees which assumed a square view (wrong), so I removed it,
3678 // Quake2 has it disabled as well.
3680 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3681 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3682 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3683 //PlaneClassify(&frustum[0]);
3685 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3686 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3687 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3688 //PlaneClassify(&frustum[1]);
3690 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3691 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3692 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3693 //PlaneClassify(&frustum[2]);
3695 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3696 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3697 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3698 //PlaneClassify(&frustum[3]);
3701 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3702 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3703 //PlaneClassify(&frustum[4]);
3706 void R_View_Update(void)
3708 R_View_SetFrustum();
3709 R_View_WorldVisibility(r_refdef.view.useclipplane);
3710 R_View_UpdateEntityVisible();
3711 R_View_UpdateEntityLighting();
3714 void R_SetupView(qboolean allowwaterclippingplane)
3716 const double *customclipplane = NULL;
3718 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3720 // LordHavoc: couldn't figure out how to make this approach the
3721 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3722 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3723 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3724 dist = r_refdef.view.clipplane.dist;
3725 plane[0] = r_refdef.view.clipplane.normal[0];
3726 plane[1] = r_refdef.view.clipplane.normal[1];
3727 plane[2] = r_refdef.view.clipplane.normal[2];
3729 customclipplane = plane;
3732 if (!r_refdef.view.useperspective)
3733 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - 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);
3734 else if (gl_stencil && r_useinfinitefarclip.integer)
3735 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - 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);
3737 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - 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);
3738 R_SetViewport(&r_refdef.view.viewport);
3741 void R_ResetViewRendering2D(void)
3743 r_viewport_t viewport;
3746 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3747 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
3748 R_SetViewport(&viewport);
3749 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3750 GL_Color(1, 1, 1, 1);
3751 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3752 GL_BlendFunc(GL_ONE, GL_ZERO);
3753 GL_AlphaTest(false);
3754 GL_ScissorTest(false);
3755 GL_DepthMask(false);
3756 GL_DepthRange(0, 1);
3757 GL_DepthTest(false);
3758 R_Mesh_Matrix(&identitymatrix);
3759 R_Mesh_ResetTextureState();
3760 GL_PolygonOffset(0, 0);
3761 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3762 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3763 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3764 qglStencilMask(~0);CHECKGLERROR
3765 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3766 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3767 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3768 R_SetupGenericShader(true);
3771 void R_ResetViewRendering3D(void)
3776 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3777 GL_Color(1, 1, 1, 1);
3778 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3779 GL_BlendFunc(GL_ONE, GL_ZERO);
3780 GL_AlphaTest(false);
3781 GL_ScissorTest(true);
3783 GL_DepthRange(0, 1);
3785 R_Mesh_Matrix(&identitymatrix);
3786 R_Mesh_ResetTextureState();
3787 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3788 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3789 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3790 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3791 qglStencilMask(~0);CHECKGLERROR
3792 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3793 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3794 GL_CullFace(r_refdef.view.cullface_back);
3795 R_SetupGenericShader(true);
3798 void R_RenderScene(void);
3799 void R_RenderWaterPlanes(void);
3801 static void R_Water_StartFrame(void)
3804 int waterwidth, waterheight, texturewidth, textureheight;
3805 r_waterstate_waterplane_t *p;
3807 // set waterwidth and waterheight to the water resolution that will be
3808 // used (often less than the screen resolution for faster rendering)
3809 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3810 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3812 // calculate desired texture sizes
3813 // can't use water if the card does not support the texture size
3814 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3815 texturewidth = textureheight = waterwidth = waterheight = 0;
3816 else if (gl_support_arb_texture_non_power_of_two)
3818 texturewidth = waterwidth;
3819 textureheight = waterheight;
3823 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3824 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3827 // allocate textures as needed
3828 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3830 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3831 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3833 if (p->texture_refraction)
3834 R_FreeTexture(p->texture_refraction);
3835 p->texture_refraction = NULL;
3836 if (p->texture_reflection)
3837 R_FreeTexture(p->texture_reflection);
3838 p->texture_reflection = NULL;
3840 memset(&r_waterstate, 0, sizeof(r_waterstate));
3841 r_waterstate.texturewidth = texturewidth;
3842 r_waterstate.textureheight = textureheight;
3845 if (r_waterstate.texturewidth)
3847 r_waterstate.enabled = true;
3849 // when doing a reduced render (HDR) we want to use a smaller area
3850 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3851 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3853 // set up variables that will be used in shader setup
3854 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3855 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3856 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3857 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3860 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3861 r_waterstate.numwaterplanes = 0;
3864 void R_Water_AddWaterPlane(msurface_t *surface)
3866 int triangleindex, planeindex;
3872 r_waterstate_waterplane_t *p;
3873 texture_t *t = R_GetCurrentTexture(surface->texture);
3874 // just use the first triangle with a valid normal for any decisions
3875 VectorClear(normal);
3876 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3878 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3879 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3880 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3881 TriangleNormal(vert[0], vert[1], vert[2], normal);
3882 if (VectorLength2(normal) >= 0.001)
3886 VectorCopy(normal, plane.normal);
3887 VectorNormalize(plane.normal);
3888 plane.dist = DotProduct(vert[0], plane.normal);
3889 PlaneClassify(&plane);
3890 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3892 // skip backfaces (except if nocullface is set)
3893 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3895 VectorNegate(plane.normal, plane.normal);
3897 PlaneClassify(&plane);
3901 // find a matching plane if there is one
3902 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3903 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3905 if (planeindex >= r_waterstate.maxwaterplanes)
3906 return; // nothing we can do, out of planes
3908 // if this triangle does not fit any known plane rendered this frame, add one
3909 if (planeindex >= r_waterstate.numwaterplanes)
3911 // store the new plane
3912 r_waterstate.numwaterplanes++;
3914 // clear materialflags and pvs
3915 p->materialflags = 0;
3916 p->pvsvalid = false;
3918 // merge this surface's materialflags into the waterplane
3919 p->materialflags |= t->currentmaterialflags;
3920 // merge this surface's PVS into the waterplane
3921 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3922 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3923 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3925 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3930 static void R_Water_ProcessPlanes(void)
3932 r_refdef_view_t originalview;
3933 r_refdef_view_t myview;
3935 r_waterstate_waterplane_t *p;
3937 originalview = r_refdef.view;
3939 // make sure enough textures are allocated
3940 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3942 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3944 if (!p->texture_refraction)
3945 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);
3946 if (!p->texture_refraction)
3950 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3952 if (!p->texture_reflection)
3953 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);
3954 if (!p->texture_reflection)
3960 r_refdef.view = originalview;
3961 r_refdef.view.showdebug = false;
3962 r_refdef.view.width = r_waterstate.waterwidth;
3963 r_refdef.view.height = r_waterstate.waterheight;
3964 r_refdef.view.useclipplane = true;
3965 myview = r_refdef.view;
3966 r_waterstate.renderingscene = true;
3967 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3969 // render the normal view scene and copy into texture
3970 // (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)
3971 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3973 r_refdef.view = myview;
3974 r_refdef.view.clipplane = p->plane;
3975 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3976 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3977 PlaneClassify(&r_refdef.view.clipplane);
3979 R_ResetViewRendering3D();
3980 R_ClearScreen(r_refdef.fogenabled);
3984 // copy view into the screen texture
3985 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3986 GL_ActiveTexture(0);
3988 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
3991 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3993 r_refdef.view = myview;
3994 // render reflected scene and copy into texture
3995 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3996 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3997 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3998 r_refdef.view.clipplane = p->plane;
3999 // reverse the cullface settings for this render
4000 r_refdef.view.cullface_front = GL_FRONT;
4001 r_refdef.view.cullface_back = GL_BACK;
4002 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4004 r_refdef.view.usecustompvs = true;
4006 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4008 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4011 R_ResetViewRendering3D();
4012 R_ClearScreen(r_refdef.fogenabled);
4016 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4017 GL_ActiveTexture(0);
4019 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4022 r_waterstate.renderingscene = false;
4023 r_refdef.view = originalview;
4024 R_ResetViewRendering3D();
4025 R_ClearScreen(r_refdef.fogenabled);
4029 r_refdef.view = originalview;
4030 r_waterstate.renderingscene = false;
4031 Cvar_SetValueQuick(&r_water, 0);
4032 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4036 void R_Bloom_StartFrame(void)
4038 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4040 // set bloomwidth and bloomheight to the bloom resolution that will be
4041 // used (often less than the screen resolution for faster rendering)
4042 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4043 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4044 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4045 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
4046 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
4048 // calculate desired texture sizes
4049 if (gl_support_arb_texture_non_power_of_two)
4051 screentexturewidth = r_refdef.view.width;
4052 screentextureheight = r_refdef.view.height;
4053 bloomtexturewidth = r_bloomstate.bloomwidth;
4054 bloomtextureheight = r_bloomstate.bloomheight;
4058 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4059 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4060 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4061 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4064 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))
4066 Cvar_SetValueQuick(&r_hdr, 0);
4067 Cvar_SetValueQuick(&r_bloom, 0);
4068 Cvar_SetValueQuick(&r_motionblur, 0);
4069 Cvar_SetValueQuick(&r_damageblur, 0);
4072 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)))
4073 screentexturewidth = screentextureheight = 0;
4074 if (!r_hdr.integer && !r_bloom.integer)
4075 bloomtexturewidth = bloomtextureheight = 0;
4077 // allocate textures as needed
4078 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4080 if (r_bloomstate.texture_screen)
4081 R_FreeTexture(r_bloomstate.texture_screen);
4082 r_bloomstate.texture_screen = NULL;
4083 r_bloomstate.screentexturewidth = screentexturewidth;
4084 r_bloomstate.screentextureheight = screentextureheight;
4085 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4086 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);
4088 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4090 if (r_bloomstate.texture_bloom)
4091 R_FreeTexture(r_bloomstate.texture_bloom);
4092 r_bloomstate.texture_bloom = NULL;
4093 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4094 r_bloomstate.bloomtextureheight = bloomtextureheight;
4095 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4096 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);
4099 // when doing a reduced render (HDR) we want to use a smaller area
4100 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4101 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4102 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4103 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4104 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4106 // set up a texcoord array for the full resolution screen image
4107 // (we have to keep this around to copy back during final render)
4108 r_bloomstate.screentexcoord2f[0] = 0;
4109 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4110 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4111 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4112 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4113 r_bloomstate.screentexcoord2f[5] = 0;
4114 r_bloomstate.screentexcoord2f[6] = 0;
4115 r_bloomstate.screentexcoord2f[7] = 0;
4117 // set up a texcoord array for the reduced resolution bloom image
4118 // (which will be additive blended over the screen image)
4119 r_bloomstate.bloomtexcoord2f[0] = 0;
4120 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4121 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4122 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4123 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4124 r_bloomstate.bloomtexcoord2f[5] = 0;
4125 r_bloomstate.bloomtexcoord2f[6] = 0;
4126 r_bloomstate.bloomtexcoord2f[7] = 0;
4128 if (r_hdr.integer || r_bloom.integer)
4130 r_bloomstate.enabled = true;
4131 r_bloomstate.hdr = r_hdr.integer != 0;
4134 R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
4137 void R_Bloom_CopyBloomTexture(float colorscale)
4139 r_refdef.stats.bloom++;
4141 // scale down screen texture to the bloom texture size
4143 R_SetViewport(&r_bloomstate.viewport);
4144 GL_BlendFunc(GL_ONE, GL_ZERO);
4145 GL_Color(colorscale, colorscale, colorscale, 1);
4146 // TODO: optimize with multitexture or GLSL
4147 R_SetupGenericShader(true);
4148 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4149 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4150 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4151 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4153 // we now have a bloom image in the framebuffer
4154 // copy it into the bloom image texture for later processing
4155 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4156 GL_ActiveTexture(0);
4158 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4159 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4162 void R_Bloom_CopyHDRTexture(void)
4164 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4165 GL_ActiveTexture(0);
4167 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4168 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4171 void R_Bloom_MakeTexture(void)
4174 float xoffset, yoffset, r, brighten;
4176 r_refdef.stats.bloom++;
4178 R_ResetViewRendering2D();
4179 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4180 R_Mesh_ColorPointer(NULL, 0, 0);
4181 R_SetupGenericShader(true);
4183 // we have a bloom image in the framebuffer
4185 R_SetViewport(&r_bloomstate.viewport);
4187 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4190 r = bound(0, r_bloom_colorexponent.value / x, 1);
4191 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4192 GL_Color(r, r, r, 1);
4193 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4194 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4195 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4196 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4198 // copy the vertically blurred bloom view to a texture
4199 GL_ActiveTexture(0);
4201 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4202 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4205 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4206 brighten = r_bloom_brighten.value;
4208 brighten *= r_hdr_range.value;
4209 brighten = sqrt(brighten);
4211 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4212 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4213 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4215 for (dir = 0;dir < 2;dir++)
4217 // blend on at multiple vertical offsets to achieve a vertical blur
4218 // TODO: do offset blends using GLSL
4219 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4220 GL_BlendFunc(GL_ONE, GL_ZERO);
4221 for (x = -range;x <= range;x++)
4223 if (!dir){xoffset = 0;yoffset = x;}
4224 else {xoffset = x;yoffset = 0;}
4225 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4226 yoffset /= (float)r_bloomstate.bloomtextureheight;
4227 // compute a texcoord array with the specified x and y offset
4228 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4229 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4230 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4231 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4232 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4233 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4234 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4235 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4236 // this r value looks like a 'dot' particle, fading sharply to
4237 // black at the edges
4238 // (probably not realistic but looks good enough)
4239 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4240 //r = brighten/(range*2+1);
4241 r = brighten / (range * 2 + 1);
4243 r *= (1 - x*x/(float)(range*range));
4244 GL_Color(r, r, r, 1);
4245 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4246 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4247 GL_BlendFunc(GL_ONE, GL_ONE);
4250 // copy the vertically blurred bloom view to a texture
4251 GL_ActiveTexture(0);
4253 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4254 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4257 // apply subtract last
4258 // (just like it would be in a GLSL shader)
4259 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4261 GL_BlendFunc(GL_ONE, GL_ZERO);
4262 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4263 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4264 GL_Color(1, 1, 1, 1);
4265 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4266 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4268 GL_BlendFunc(GL_ONE, GL_ONE);
4269 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4270 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4271 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4272 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4273 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4274 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4275 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4277 // copy the darkened bloom view to a texture
4278 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4279 GL_ActiveTexture(0);
4281 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4282 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4286 void R_HDR_RenderBloomTexture(void)
4288 int oldwidth, oldheight;
4289 float oldcolorscale;
4291 oldcolorscale = r_refdef.view.colorscale;
4292 oldwidth = r_refdef.view.width;
4293 oldheight = r_refdef.view.height;
4294 r_refdef.view.width = r_bloomstate.bloomwidth;
4295 r_refdef.view.height = r_bloomstate.bloomheight;
4297 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4298 // TODO: add exposure compensation features
4299 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4301 r_refdef.view.showdebug = false;
4302 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4304 R_ResetViewRendering3D();
4306 R_ClearScreen(r_refdef.fogenabled);
4307 if (r_timereport_active)
4308 R_TimeReport("HDRclear");
4311 if (r_timereport_active)
4312 R_TimeReport("visibility");
4314 // only do secondary renders with HDR if r_hdr is 2 or higher
4315 r_waterstate.numwaterplanes = 0;
4316 if (r_waterstate.enabled && r_hdr.integer >= 2)
4317 R_RenderWaterPlanes();
4319 r_refdef.view.showdebug = true;
4321 r_waterstate.numwaterplanes = 0;
4323 R_ResetViewRendering2D();
4325 R_Bloom_CopyHDRTexture();
4326 R_Bloom_MakeTexture();
4328 // restore the view settings
4329 r_refdef.view.width = oldwidth;
4330 r_refdef.view.height = oldheight;
4331 r_refdef.view.colorscale = oldcolorscale;
4333 R_ResetViewRendering3D();
4335 R_ClearScreen(r_refdef.fogenabled);
4336 if (r_timereport_active)
4337 R_TimeReport("viewclear");
4340 static void R_BlendView(void)
4342 if (r_bloomstate.texture_screen)
4344 // make sure the buffer is available
4345 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4347 R_ResetViewRendering2D();
4348 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4349 R_Mesh_ColorPointer(NULL, 0, 0);
4350 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4351 GL_ActiveTexture(0);CHECKGLERROR
4353 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4355 // declare variables
4357 static float avgspeed;
4359 speed = VectorLength(cl.movement_velocity);
4361 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4362 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4364 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4365 speed = bound(0, speed, 1);
4366 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4368 // calculate values into a standard alpha
4369 cl.motionbluralpha = 1 - exp(-
4371 (r_motionblur.value * speed / 80)
4373 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4376 max(0.0001, cl.time - cl.oldtime) // fps independent
4379 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4380 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4382 if (cl.motionbluralpha > 0)
4384 R_SetupGenericShader(true);
4385 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4386 GL_Color(1, 1, 1, cl.motionbluralpha);
4387 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4388 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4389 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4390 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4394 // copy view into the screen texture
4395 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4396 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4399 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4401 unsigned int permutation =
4402 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4403 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4404 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4405 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4406 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4408 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4410 // render simple bloom effect
4411 // copy the screen and shrink it and darken it for the bloom process
4412 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4413 // make the bloom texture
4414 R_Bloom_MakeTexture();
4417 R_ResetViewRendering2D();
4418 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4419 R_Mesh_ColorPointer(NULL, 0, 0);
4420 GL_Color(1, 1, 1, 1);
4421 GL_BlendFunc(GL_ONE, GL_ZERO);
4422 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4423 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4424 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4425 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4426 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4427 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4428 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4429 if (r_glsl_permutation->loc_TintColor >= 0)
4430 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4431 if (r_glsl_permutation->loc_ClientTime >= 0)
4432 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4433 if (r_glsl_permutation->loc_PixelSize >= 0)
4434 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4435 if (r_glsl_permutation->loc_UserVec1 >= 0)
4437 float a=0, b=0, c=0, d=0;
4438 #if _MSC_VER >= 1400
4439 #define sscanf sscanf_s
4441 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4442 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4444 if (r_glsl_permutation->loc_UserVec2 >= 0)
4446 float a=0, b=0, c=0, d=0;
4447 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4448 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4450 if (r_glsl_permutation->loc_UserVec3 >= 0)
4452 float a=0, b=0, c=0, d=0;
4453 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4454 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4456 if (r_glsl_permutation->loc_UserVec4 >= 0)
4458 float a=0, b=0, c=0, d=0;
4459 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4460 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4462 if (r_glsl_permutation->loc_Saturation >= 0)
4463 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4464 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4465 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4471 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4473 // render high dynamic range bloom effect
4474 // the bloom texture was made earlier this render, so we just need to
4475 // blend it onto the screen...
4476 R_ResetViewRendering2D();
4477 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4478 R_Mesh_ColorPointer(NULL, 0, 0);
4479 R_SetupGenericShader(true);
4480 GL_Color(1, 1, 1, 1);
4481 GL_BlendFunc(GL_ONE, GL_ONE);
4482 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4483 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4484 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4485 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4487 else if (r_bloomstate.texture_bloom)
4489 // render simple bloom effect
4490 // copy the screen and shrink it and darken it for the bloom process
4491 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4492 // make the bloom texture
4493 R_Bloom_MakeTexture();
4494 // put the original screen image back in place and blend the bloom
4496 R_ResetViewRendering2D();
4497 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4498 R_Mesh_ColorPointer(NULL, 0, 0);
4499 GL_Color(1, 1, 1, 1);
4500 GL_BlendFunc(GL_ONE, GL_ZERO);
4501 // do both in one pass if possible
4502 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4503 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4504 if (r_textureunits.integer >= 2 && gl_combine.integer)
4506 R_SetupGenericTwoTextureShader(GL_ADD);
4507 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4508 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4512 R_SetupGenericShader(true);
4513 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4514 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4515 // now blend on the bloom texture
4516 GL_BlendFunc(GL_ONE, GL_ONE);
4517 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4518 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4520 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4521 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4523 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4525 // apply a color tint to the whole view
4526 R_ResetViewRendering2D();
4527 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4528 R_Mesh_ColorPointer(NULL, 0, 0);
4529 R_SetupGenericShader(false);
4530 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4531 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4532 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4536 matrix4x4_t r_waterscrollmatrix;
4538 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4540 if (r_refdef.fog_density)
4542 r_refdef.fogcolor[0] = r_refdef.fog_red;
4543 r_refdef.fogcolor[1] = r_refdef.fog_green;
4544 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4548 VectorCopy(r_refdef.fogcolor, fogvec);
4549 // color.rgb *= ContrastBoost * SceneBrightness;
4550 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4551 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4552 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4553 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4558 void R_UpdateVariables(void)
4562 r_refdef.scene.ambient = r_ambient.value;
4564 r_refdef.farclip = 4096;
4565 if (r_refdef.scene.worldmodel)
4566 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4567 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4569 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4570 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4571 r_refdef.polygonfactor = 0;
4572 r_refdef.polygonoffset = 0;
4573 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4574 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4576 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4577 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4578 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4579 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4580 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4581 if (r_showsurfaces.integer)
4583 r_refdef.scene.rtworld = false;
4584 r_refdef.scene.rtworldshadows = false;
4585 r_refdef.scene.rtdlight = false;
4586 r_refdef.scene.rtdlightshadows = false;
4587 r_refdef.lightmapintensity = 0;
4590 if (gamemode == GAME_NEHAHRA)
4592 if (gl_fogenable.integer)
4594 r_refdef.oldgl_fogenable = true;
4595 r_refdef.fog_density = gl_fogdensity.value;
4596 r_refdef.fog_red = gl_fogred.value;
4597 r_refdef.fog_green = gl_foggreen.value;
4598 r_refdef.fog_blue = gl_fogblue.value;
4599 r_refdef.fog_alpha = 1;
4600 r_refdef.fog_start = 0;
4601 r_refdef.fog_end = gl_skyclip.value;
4603 else if (r_refdef.oldgl_fogenable)
4605 r_refdef.oldgl_fogenable = false;
4606 r_refdef.fog_density = 0;
4607 r_refdef.fog_red = 0;
4608 r_refdef.fog_green = 0;
4609 r_refdef.fog_blue = 0;
4610 r_refdef.fog_alpha = 0;
4611 r_refdef.fog_start = 0;
4612 r_refdef.fog_end = 0;
4616 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4617 r_refdef.fog_start = max(0, r_refdef.fog_start);
4618 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4620 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4622 if (r_refdef.fog_density && r_drawfog.integer)
4624 r_refdef.fogenabled = true;
4625 // this is the point where the fog reaches 0.9986 alpha, which we
4626 // consider a good enough cutoff point for the texture
4627 // (0.9986 * 256 == 255.6)
4628 if (r_fog_exp2.integer)
4629 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4631 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4632 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4633 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4634 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4635 // fog color was already set
4636 // update the fog texture
4637 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)
4638 R_BuildFogTexture();
4641 r_refdef.fogenabled = false;
4643 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4645 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4647 // build GLSL gamma texture
4648 #define RAMPWIDTH 256
4649 unsigned short ramp[RAMPWIDTH * 3];
4650 unsigned char rampbgr[RAMPWIDTH][4];
4653 r_texture_gammaramps_serial = vid_gammatables_serial;
4655 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4656 for(i = 0; i < RAMPWIDTH; ++i)
4658 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4659 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4660 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4663 if (r_texture_gammaramps)
4665 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4669 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);
4675 // remove GLSL gamma texture
4679 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4680 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4686 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4687 if( scenetype != r_currentscenetype ) {
4688 // store the old scenetype
4689 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4690 r_currentscenetype = scenetype;
4691 // move in the new scene
4692 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4701 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4703 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4704 if( scenetype == r_currentscenetype ) {
4705 return &r_refdef.scene;
4707 return &r_scenes_store[ scenetype ];
4716 void R_RenderView(void)
4718 if (r_timereport_active)
4719 R_TimeReport("start");
4720 r_frame++; // used only by R_GetCurrentTexture
4721 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4723 R_AnimCache_NewFrame();
4725 if (r_refdef.view.isoverlay)
4727 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4728 GL_Clear( GL_DEPTH_BUFFER_BIT );
4729 R_TimeReport("depthclear");
4731 r_refdef.view.showdebug = false;
4733 r_waterstate.enabled = false;
4734 r_waterstate.numwaterplanes = 0;
4742 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4743 return; //Host_Error ("R_RenderView: NULL worldmodel");
4745 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4747 // break apart the view matrix into vectors for various purposes
4748 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4749 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4750 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4751 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4752 // make an inverted copy of the view matrix for tracking sprites
4753 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4755 R_Shadow_UpdateWorldLightSelection();
4757 R_Bloom_StartFrame();
4758 R_Water_StartFrame();
4761 if (r_timereport_active)
4762 R_TimeReport("viewsetup");
4764 R_ResetViewRendering3D();
4766 if (r_refdef.view.clear || r_refdef.fogenabled)
4768 R_ClearScreen(r_refdef.fogenabled);
4769 if (r_timereport_active)
4770 R_TimeReport("viewclear");
4772 r_refdef.view.clear = true;
4774 // this produces a bloom texture to be used in R_BlendView() later
4776 R_HDR_RenderBloomTexture();
4778 r_refdef.view.showdebug = true;
4781 if (r_timereport_active)
4782 R_TimeReport("visibility");
4784 r_waterstate.numwaterplanes = 0;
4785 if (r_waterstate.enabled)
4786 R_RenderWaterPlanes();
4789 r_waterstate.numwaterplanes = 0;
4792 if (r_timereport_active)
4793 R_TimeReport("blendview");
4795 GL_Scissor(0, 0, vid.width, vid.height);
4796 GL_ScissorTest(false);
4800 void R_RenderWaterPlanes(void)
4802 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4804 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4805 if (r_timereport_active)
4806 R_TimeReport("waterworld");
4809 // don't let sound skip if going slow
4810 if (r_refdef.scene.extraupdate)
4813 R_DrawModelsAddWaterPlanes();
4814 if (r_timereport_active)
4815 R_TimeReport("watermodels");
4817 if (r_waterstate.numwaterplanes)
4819 R_Water_ProcessPlanes();
4820 if (r_timereport_active)
4821 R_TimeReport("waterscenes");
4825 extern void R_DrawLightningBeams (void);
4826 extern void VM_CL_AddPolygonsToMeshQueue (void);
4827 extern void R_DrawPortals (void);
4828 extern cvar_t cl_locs_show;
4829 static void R_DrawLocs(void);
4830 static void R_DrawEntityBBoxes(void);
4831 void R_RenderScene(void)
4833 r_refdef.stats.renders++;
4837 // don't let sound skip if going slow
4838 if (r_refdef.scene.extraupdate)
4841 R_MeshQueue_BeginScene();
4845 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);
4847 if (cl.csqc_vidvars.drawworld)
4849 // don't let sound skip if going slow
4850 if (r_refdef.scene.extraupdate)
4853 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4855 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4856 if (r_timereport_active)
4857 R_TimeReport("worldsky");
4860 if (R_DrawBrushModelsSky() && r_timereport_active)
4861 R_TimeReport("bmodelsky");
4863 if (skyrendermasked && skyrenderlater)
4865 // we have to force off the water clipping plane while rendering sky
4872 R_AnimCache_CacheVisibleEntities();
4874 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4876 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4877 if (r_timereport_active)
4878 R_TimeReport("worlddepth");
4880 if (r_depthfirst.integer >= 2)
4882 R_DrawModelsDepth();
4883 if (r_timereport_active)
4884 R_TimeReport("modeldepth");
4887 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4889 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4890 if (r_timereport_active)
4891 R_TimeReport("world");
4894 // don't let sound skip if going slow
4895 if (r_refdef.scene.extraupdate)
4899 if (r_timereport_active)
4900 R_TimeReport("models");
4902 // don't let sound skip if going slow
4903 if (r_refdef.scene.extraupdate)
4906 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4908 R_DrawModelShadows();
4909 R_ResetViewRendering3D();
4910 // don't let sound skip if going slow
4911 if (r_refdef.scene.extraupdate)
4915 R_ShadowVolumeLighting(false);
4916 if (r_timereport_active)
4917 R_TimeReport("rtlights");
4919 // don't let sound skip if going slow
4920 if (r_refdef.scene.extraupdate)
4923 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4925 R_DrawModelShadows();
4926 R_ResetViewRendering3D();
4927 // don't let sound skip if going slow
4928 if (r_refdef.scene.extraupdate)
4932 if (cl.csqc_vidvars.drawworld)
4934 R_DrawLightningBeams();
4935 if (r_timereport_active)
4936 R_TimeReport("lightning");
4939 if (r_timereport_active)
4940 R_TimeReport("decals");
4943 if (r_timereport_active)
4944 R_TimeReport("particles");
4947 if (r_timereport_active)
4948 R_TimeReport("explosions");
4951 R_SetupGenericShader(true);
4952 VM_CL_AddPolygonsToMeshQueue();
4954 if (r_refdef.view.showdebug)
4956 if (cl_locs_show.integer)
4959 if (r_timereport_active)
4960 R_TimeReport("showlocs");
4963 if (r_drawportals.integer)
4966 if (r_timereport_active)
4967 R_TimeReport("portals");
4970 if (r_showbboxes.value > 0)
4972 R_DrawEntityBBoxes();
4973 if (r_timereport_active)
4974 R_TimeReport("bboxes");
4978 R_SetupGenericShader(true);
4979 R_MeshQueue_RenderTransparent();
4980 if (r_timereport_active)
4981 R_TimeReport("drawtrans");
4983 R_SetupGenericShader(true);
4985 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))
4987 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4988 if (r_timereport_active)
4989 R_TimeReport("worlddebug");
4990 R_DrawModelsDebug();
4991 if (r_timereport_active)
4992 R_TimeReport("modeldebug");
4995 R_SetupGenericShader(true);
4997 if (cl.csqc_vidvars.drawworld)
5000 if (r_timereport_active)
5001 R_TimeReport("coronas");
5004 // don't let sound skip if going slow
5005 if (r_refdef.scene.extraupdate)
5008 R_ResetViewRendering2D();
5011 static const unsigned short bboxelements[36] =
5021 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5024 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5025 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5026 GL_DepthMask(false);
5027 GL_DepthRange(0, 1);
5028 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5029 R_Mesh_Matrix(&identitymatrix);
5030 R_Mesh_ResetTextureState();
5032 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5033 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5034 rsurface.fograngerecip = r_refdef.fograngerecip;
5036 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5037 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5038 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5039 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5040 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5041 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5042 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5043 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5044 R_FillColors(color4f, 8, cr, cg, cb, ca);
5045 if (r_refdef.fogenabled)
5047 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5049 f1 = RSurf_FogVertex(v);
5051 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5052 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5053 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5056 R_Mesh_VertexPointer(vertex3f, 0, 0);
5057 R_Mesh_ColorPointer(color4f, 0, 0);
5058 R_Mesh_ResetTextureState();
5059 R_SetupGenericShader(false);
5060 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5063 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5067 prvm_edict_t *edict;
5068 prvm_prog_t *prog_save = prog;
5070 // this function draws bounding boxes of server entities
5074 GL_CullFace(GL_NONE);
5075 R_SetupGenericShader(false);
5079 for (i = 0;i < numsurfaces;i++)
5081 edict = PRVM_EDICT_NUM(surfacelist[i]);
5082 switch ((int)edict->fields.server->solid)
5084 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5085 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5086 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5087 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5088 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5089 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5091 color[3] *= r_showbboxes.value;
5092 color[3] = bound(0, color[3], 1);
5093 GL_DepthTest(!r_showdisabledepthtest.integer);
5094 GL_CullFace(r_refdef.view.cullface_front);
5095 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5101 static void R_DrawEntityBBoxes(void)
5104 prvm_edict_t *edict;
5106 prvm_prog_t *prog_save = prog;
5108 // this function draws bounding boxes of server entities
5114 for (i = 0;i < prog->num_edicts;i++)
5116 edict = PRVM_EDICT_NUM(i);
5117 if (edict->priv.server->free)
5119 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5120 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5122 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5124 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5125 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5131 unsigned short nomodelelements[24] =
5143 float nomodelvertex3f[6*3] =
5153 float nomodelcolor4f[6*4] =
5155 0.0f, 0.0f, 0.5f, 1.0f,
5156 0.0f, 0.0f, 0.5f, 1.0f,
5157 0.0f, 0.5f, 0.0f, 1.0f,
5158 0.0f, 0.5f, 0.0f, 1.0f,
5159 0.5f, 0.0f, 0.0f, 1.0f,
5160 0.5f, 0.0f, 0.0f, 1.0f
5163 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5169 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5170 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5171 rsurface.fograngerecip = r_refdef.fograngerecip;
5173 // this is only called once per entity so numsurfaces is always 1, and
5174 // surfacelist is always {0}, so this code does not handle batches
5175 R_Mesh_Matrix(&ent->matrix);
5177 if (rsurface.ent_flags & RENDER_ADDITIVE)
5179 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5180 GL_DepthMask(false);
5182 else if (ent->alpha < 1)
5184 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5185 GL_DepthMask(false);
5189 GL_BlendFunc(GL_ONE, GL_ZERO);
5192 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5193 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5194 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
5195 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5196 R_SetupGenericShader(false);
5197 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
5198 if (r_refdef.fogenabled)
5201 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5202 R_Mesh_ColorPointer(color4f, 0, 0);
5203 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5204 f1 = RSurf_FogVertex(org);
5206 for (i = 0, c = color4f;i < 6;i++, c += 4)
5208 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5209 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5210 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5214 else if (ent->alpha != 1)
5216 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5217 R_Mesh_ColorPointer(color4f, 0, 0);
5218 for (i = 0, c = color4f;i < 6;i++, c += 4)
5222 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
5223 R_Mesh_ResetTextureState();
5224 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
5227 void R_DrawNoModel(entity_render_t *ent)
5230 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5231 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5232 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5234 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5237 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5239 vec3_t right1, right2, diff, normal;
5241 VectorSubtract (org2, org1, normal);
5243 // calculate 'right' vector for start
5244 VectorSubtract (r_refdef.view.origin, org1, diff);
5245 CrossProduct (normal, diff, right1);
5246 VectorNormalize (right1);
5248 // calculate 'right' vector for end
5249 VectorSubtract (r_refdef.view.origin, org2, diff);
5250 CrossProduct (normal, diff, right2);
5251 VectorNormalize (right2);
5253 vert[ 0] = org1[0] + width * right1[0];
5254 vert[ 1] = org1[1] + width * right1[1];
5255 vert[ 2] = org1[2] + width * right1[2];
5256 vert[ 3] = org1[0] - width * right1[0];
5257 vert[ 4] = org1[1] - width * right1[1];
5258 vert[ 5] = org1[2] - width * right1[2];
5259 vert[ 6] = org2[0] - width * right2[0];
5260 vert[ 7] = org2[1] - width * right2[1];
5261 vert[ 8] = org2[2] - width * right2[2];
5262 vert[ 9] = org2[0] + width * right2[0];
5263 vert[10] = org2[1] + width * right2[1];
5264 vert[11] = org2[2] + width * right2[2];
5267 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5269 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)
5271 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
5275 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5276 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5277 rsurface.fograngerecip = r_refdef.fograngerecip;
5279 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
5280 fog = RSurf_FogVertex(origin);
5282 R_Mesh_Matrix(&identitymatrix);
5283 GL_BlendFunc(blendfunc1, blendfunc2);
5285 GL_CullFace(GL_NONE);
5287 GL_DepthMask(false);
5288 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5289 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5290 GL_DepthTest(!depthdisable);
5292 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5293 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5294 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5295 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5296 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5297 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5298 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5299 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5300 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5301 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5302 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5303 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5305 R_Mesh_VertexPointer(vertex3f, 0, 0);
5306 R_Mesh_ColorPointer(NULL, 0, 0);
5307 R_Mesh_ResetTextureState();
5308 R_SetupGenericShader(true);
5309 R_Mesh_TexBind(0, R_GetTexture(texture));
5310 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5311 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5312 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5313 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5315 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5317 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5318 GL_BlendFunc(blendfunc1, GL_ONE);
5320 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5321 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5325 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5330 VectorSet(v, x, y, z);
5331 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5332 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5334 if (i == mesh->numvertices)
5336 if (mesh->numvertices < mesh->maxvertices)
5338 VectorCopy(v, vertex3f);
5339 mesh->numvertices++;
5341 return mesh->numvertices;
5347 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5351 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5352 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5353 e = mesh->element3i + mesh->numtriangles * 3;
5354 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5356 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5357 if (mesh->numtriangles < mesh->maxtriangles)
5362 mesh->numtriangles++;
5364 element[1] = element[2];
5368 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5372 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5373 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5374 e = mesh->element3i + mesh->numtriangles * 3;
5375 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5377 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5378 if (mesh->numtriangles < mesh->maxtriangles)
5383 mesh->numtriangles++;
5385 element[1] = element[2];
5389 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5390 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5392 int planenum, planenum2;
5395 mplane_t *plane, *plane2;
5397 double temppoints[2][256*3];
5398 // figure out how large a bounding box we need to properly compute this brush
5400 for (w = 0;w < numplanes;w++)
5401 maxdist = max(maxdist, fabs(planes[w].dist));
5402 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5403 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5404 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5408 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5409 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5411 if (planenum2 == planenum)
5413 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);
5416 if (tempnumpoints < 3)
5418 // generate elements forming a triangle fan for this polygon
5419 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5423 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)
5425 texturelayer_t *layer;
5426 layer = t->currentlayers + t->currentnumlayers++;
5428 layer->depthmask = depthmask;
5429 layer->blendfunc1 = blendfunc1;
5430 layer->blendfunc2 = blendfunc2;
5431 layer->texture = texture;
5432 layer->texmatrix = *matrix;
5433 layer->color[0] = r * r_refdef.view.colorscale;
5434 layer->color[1] = g * r_refdef.view.colorscale;
5435 layer->color[2] = b * r_refdef.view.colorscale;
5436 layer->color[3] = a;
5439 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5442 index = parms[2] + r_refdef.scene.time * parms[3];
5443 index -= floor(index);
5447 case Q3WAVEFUNC_NONE:
5448 case Q3WAVEFUNC_NOISE:
5449 case Q3WAVEFUNC_COUNT:
5452 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5453 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5454 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5455 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5456 case Q3WAVEFUNC_TRIANGLE:
5458 f = index - floor(index);
5469 return (float)(parms[0] + parms[1] * f);
5472 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5477 matrix4x4_t matrix, temp;
5478 switch(tcmod->tcmod)
5482 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5483 matrix = r_waterscrollmatrix;
5485 matrix = identitymatrix;
5487 case Q3TCMOD_ENTITYTRANSLATE:
5488 // this is used in Q3 to allow the gamecode to control texcoord
5489 // scrolling on the entity, which is not supported in darkplaces yet.
5490 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5492 case Q3TCMOD_ROTATE:
5493 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5494 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5495 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5498 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5500 case Q3TCMOD_SCROLL:
5501 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5503 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5504 w = (int) tcmod->parms[0];
5505 h = (int) tcmod->parms[1];
5506 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5508 idx = (int) floor(f * w * h);
5509 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5511 case Q3TCMOD_STRETCH:
5512 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5513 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5515 case Q3TCMOD_TRANSFORM:
5516 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5517 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5518 VectorSet(tcmat + 6, 0 , 0 , 1);
5519 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5520 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5522 case Q3TCMOD_TURBULENT:
5523 // this is handled in the RSurf_PrepareVertices function
5524 matrix = identitymatrix;
5528 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5531 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5533 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5534 char name[MAX_QPATH];
5535 skinframe_t *skinframe;
5536 unsigned char pixels[296*194];
5537 strlcpy(cache->name, skinname, sizeof(cache->name));
5538 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5539 if (developer_loading.integer)
5540 Con_Printf("loading %s\n", name);
5541 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5542 if (!skinframe || !skinframe->base)
5545 fs_offset_t filesize;
5547 f = FS_LoadFile(name, tempmempool, true, &filesize);
5550 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5551 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5555 cache->skinframe = skinframe;
5558 texture_t *R_GetCurrentTexture(texture_t *t)
5561 const entity_render_t *ent = rsurface.entity;
5562 dp_model_t *model = ent->model;
5563 q3shaderinfo_layer_tcmod_t *tcmod;
5565 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5566 return t->currentframe;
5567 t->update_lastrenderframe = r_frame;
5568 t->update_lastrenderentity = (void *)ent;
5570 // switch to an alternate material if this is a q1bsp animated material
5572 texture_t *texture = t;
5573 int s = rsurface.ent_skinnum;
5574 if ((unsigned int)s >= (unsigned int)model->numskins)
5576 if (model->skinscenes)
5578 if (model->skinscenes[s].framecount > 1)
5579 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5581 s = model->skinscenes[s].firstframe;
5584 t = t + s * model->num_surfaces;
5587 // use an alternate animation if the entity's frame is not 0,
5588 // and only if the texture has an alternate animation
5589 if (rsurface.frameblend[0].subframe != 0 && t->anim_total[1])
5590 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5592 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5594 texture->currentframe = t;
5597 // update currentskinframe to be a qw skin or animation frame
5598 if (rsurface.ent_qwskin >= 0)
5600 i = rsurface.ent_qwskin;
5601 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5603 r_qwskincache_size = cl.maxclients;
5605 Mem_Free(r_qwskincache);
5606 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5608 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5609 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5610 t->currentskinframe = r_qwskincache[i].skinframe;
5611 if (t->currentskinframe == NULL)
5612 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5614 else if (t->numskinframes >= 2)
5615 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5616 if (t->backgroundnumskinframes >= 2)
5617 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5619 t->currentmaterialflags = t->basematerialflags;
5620 t->currentalpha = rsurface.ent_color[3];
5621 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5622 t->currentalpha *= r_wateralpha.value;
5623 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5624 t->currentalpha *= t->r_water_wateralpha;
5625 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5626 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5627 if (!(rsurface.ent_flags & RENDER_LIGHT))
5628 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5629 else if (rsurface.modeltexcoordlightmap2f == NULL)
5631 // pick a model lighting mode
5632 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5633 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5635 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5637 if (rsurface.ent_flags & RENDER_ADDITIVE)
5638 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5639 else if (t->currentalpha < 1)
5640 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5641 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5642 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5643 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5644 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5645 if (t->backgroundnumskinframes)
5646 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5647 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5649 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5650 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5653 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5655 // there is no tcmod
5656 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5658 t->currenttexmatrix = r_waterscrollmatrix;
5659 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5663 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5664 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5667 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5668 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5669 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5670 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5672 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5673 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5674 t->glosstexture = r_texture_black;
5675 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5676 t->backgroundglosstexture = r_texture_black;
5677 t->specularpower = r_shadow_glossexponent.value;
5678 // TODO: store reference values for these in the texture?
5679 t->specularscale = 0;
5680 if (r_shadow_gloss.integer > 0)
5682 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5684 if (r_shadow_glossintensity.value > 0)
5686 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5687 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5688 t->specularscale = r_shadow_glossintensity.value;
5691 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5693 t->glosstexture = r_texture_white;
5694 t->backgroundglosstexture = r_texture_white;
5695 t->specularscale = r_shadow_gloss2intensity.value;
5696 t->specularpower = r_shadow_gloss2exponent.value;
5699 t->specularscale *= t->specularscalemod;
5700 t->specularpower *= t->specularpowermod;
5702 // lightmaps mode looks bad with dlights using actual texturing, so turn
5703 // off the colormap and glossmap, but leave the normalmap on as it still
5704 // accurately represents the shading involved
5705 if (gl_lightmaps.integer)
5707 t->basetexture = r_texture_grey128;
5708 t->backgroundbasetexture = NULL;
5709 t->specularscale = 0;
5710 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5713 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5714 VectorClear(t->dlightcolor);
5715 t->currentnumlayers = 0;
5716 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5719 int blendfunc1, blendfunc2;
5721 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5723 blendfunc1 = GL_SRC_ALPHA;
5724 blendfunc2 = GL_ONE;
5726 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5728 blendfunc1 = GL_SRC_ALPHA;
5729 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5731 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5733 blendfunc1 = t->customblendfunc[0];
5734 blendfunc2 = t->customblendfunc[1];
5738 blendfunc1 = GL_ONE;
5739 blendfunc2 = GL_ZERO;
5741 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5742 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5743 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5744 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5746 // fullbright is not affected by r_refdef.lightmapintensity
5747 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]);
5748 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5749 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5750 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5751 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5755 vec3_t ambientcolor;
5757 // set the color tint used for lights affecting this surface
5758 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5760 // q3bsp has no lightmap updates, so the lightstylevalue that
5761 // would normally be baked into the lightmap must be
5762 // applied to the color
5763 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5764 if (model->type == mod_brushq3)
5765 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5766 colorscale *= r_refdef.lightmapintensity;
5767 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5768 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5769 // basic lit geometry
5770 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]);
5771 // add pants/shirt if needed
5772 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5773 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5774 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5775 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5776 // now add ambient passes if needed
5777 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5779 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]);
5780 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5781 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
5782 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5783 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
5786 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5787 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]);
5788 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5790 // if this is opaque use alpha blend which will darken the earlier
5793 // if this is an alpha blended material, all the earlier passes
5794 // were darkened by fog already, so we only need to add the fog
5795 // color ontop through the fog mask texture
5797 // if this is an additive blended material, all the earlier passes
5798 // were darkened by fog already, and we should not add fog color
5799 // (because the background was not darkened, there is no fog color
5800 // that was lost behind it).
5801 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]);
5805 return t->currentframe;
5808 rsurfacestate_t rsurface;
5810 void R_Mesh_ResizeArrays(int newvertices)
5813 if (rsurface.array_size >= newvertices)
5815 if (rsurface.array_modelvertex3f)
5816 Mem_Free(rsurface.array_modelvertex3f);
5817 rsurface.array_size = (newvertices + 1023) & ~1023;
5818 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5819 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5820 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5821 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5822 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5823 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5824 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5825 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5826 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5827 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5828 rsurface.array_color4f = base + rsurface.array_size * 27;
5829 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5832 void RSurf_ActiveWorldEntity(void)
5834 dp_model_t *model = r_refdef.scene.worldmodel;
5835 //if (rsurface.entity == r_refdef.scene.worldentity)
5837 rsurface.entity = r_refdef.scene.worldentity;
5838 rsurface.ent_skinnum = 0;
5839 rsurface.ent_qwskin = -1;
5840 rsurface.ent_shadertime = 0;
5841 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
5842 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
5843 if (rsurface.array_size < model->surfmesh.num_vertices)
5844 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5845 rsurface.matrix = identitymatrix;
5846 rsurface.inversematrix = identitymatrix;
5847 rsurface.matrixscale = 1;
5848 rsurface.inversematrixscale = 1;
5849 R_Mesh_Matrix(&identitymatrix);
5850 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5851 rsurface.fograngerecip = r_refdef.fograngerecip;
5852 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
5853 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5854 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5855 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5856 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5857 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5858 VectorSet(rsurface.glowmod, 1, 1, 1);
5859 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5860 rsurface.frameblend[0].lerp = 1;
5861 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5862 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5863 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5864 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5865 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5866 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5867 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5868 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5869 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5870 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5871 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5872 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5873 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5874 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5875 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5876 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5877 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5878 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5879 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5880 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5881 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5882 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5883 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5884 rsurface.modelelement3i = model->surfmesh.data_element3i;
5885 rsurface.modelelement3s = model->surfmesh.data_element3s;
5886 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5887 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5888 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5889 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5890 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5891 rsurface.modelsurfaces = model->data_surfaces;
5892 rsurface.generatedvertex = false;
5893 rsurface.vertex3f = rsurface.modelvertex3f;
5894 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5895 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5896 rsurface.svector3f = rsurface.modelsvector3f;
5897 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5898 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5899 rsurface.tvector3f = rsurface.modeltvector3f;
5900 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5901 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5902 rsurface.normal3f = rsurface.modelnormal3f;
5903 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5904 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5905 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5908 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5910 dp_model_t *model = ent->model;
5911 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5913 rsurface.entity = (entity_render_t *)ent;
5914 rsurface.ent_skinnum = ent->skinnum;
5915 rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
5916 rsurface.ent_shadertime = ent->shadertime;
5917 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
5918 rsurface.ent_flags = ent->flags;
5919 if (rsurface.array_size < model->surfmesh.num_vertices)
5920 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5921 rsurface.matrix = ent->matrix;
5922 rsurface.inversematrix = ent->inversematrix;
5923 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
5924 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
5925 R_Mesh_Matrix(&rsurface.matrix);
5926 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
5927 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
5928 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
5929 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
5930 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5931 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5932 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5933 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5934 VectorCopy(ent->glowmod, rsurface.glowmod);
5935 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5936 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5937 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5938 if (ent->model->brush.submodel)
5940 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5941 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5943 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5945 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5947 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5948 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5949 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5950 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5952 else if (wanttangents)
5954 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5955 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5956 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5957 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5958 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5960 else if (wantnormals)
5962 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5963 rsurface.modelsvector3f = NULL;
5964 rsurface.modeltvector3f = NULL;
5965 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5966 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5970 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5971 rsurface.modelsvector3f = NULL;
5972 rsurface.modeltvector3f = NULL;
5973 rsurface.modelnormal3f = NULL;
5974 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5976 rsurface.modelvertex3f_bufferobject = 0;
5977 rsurface.modelvertex3f_bufferoffset = 0;
5978 rsurface.modelsvector3f_bufferobject = 0;
5979 rsurface.modelsvector3f_bufferoffset = 0;
5980 rsurface.modeltvector3f_bufferobject = 0;
5981 rsurface.modeltvector3f_bufferoffset = 0;
5982 rsurface.modelnormal3f_bufferobject = 0;
5983 rsurface.modelnormal3f_bufferoffset = 0;
5984 rsurface.generatedvertex = true;
5988 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5989 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5990 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5991 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5992 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5993 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5994 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5995 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5996 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5997 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5998 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5999 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6000 rsurface.generatedvertex = false;
6002 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6003 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6004 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6005 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6006 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6007 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6008 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6009 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6010 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6011 rsurface.modelelement3i = model->surfmesh.data_element3i;
6012 rsurface.modelelement3s = model->surfmesh.data_element3s;
6013 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6014 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6015 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6016 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6017 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6018 rsurface.modelsurfaces = model->data_surfaces;
6019 rsurface.vertex3f = rsurface.modelvertex3f;
6020 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6021 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6022 rsurface.svector3f = rsurface.modelsvector3f;
6023 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6024 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6025 rsurface.tvector3f = rsurface.modeltvector3f;
6026 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6027 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6028 rsurface.normal3f = rsurface.modelnormal3f;
6029 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6030 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6031 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6034 float RSurf_FogPoint(const float *v)
6036 float len = VectorDistance(r_refdef.view.origin, v);
6037 unsigned int fogmasktableindex;
6038 fogmasktableindex = (unsigned int)(len * r_refdef.fogmasktabledistmultiplier);
6039 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6042 float RSurf_FogVertex(const float *v)
6044 float len = VectorDistance(rsurface.localvieworigin, v);
6045 unsigned int fogmasktableindex;
6046 fogmasktableindex = (unsigned int)(len * rsurface.fogmasktabledistmultiplier);
6047 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6050 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6051 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
6054 int texturesurfaceindex;
6059 const float *v1, *in_tc;
6061 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6063 q3shaderinfo_deform_t *deform;
6064 // 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
6065 if (rsurface.generatedvertex)
6067 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6068 generatenormals = true;
6069 for (i = 0;i < Q3MAXDEFORMS;i++)
6071 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6073 generatetangents = true;
6074 generatenormals = true;
6076 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6077 generatenormals = true;
6079 if (generatenormals && !rsurface.modelnormal3f)
6081 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6082 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6083 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6084 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6086 if (generatetangents && !rsurface.modelsvector3f)
6088 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6089 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6090 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6091 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6092 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6093 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6094 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);
6097 rsurface.vertex3f = rsurface.modelvertex3f;
6098 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6099 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6100 rsurface.svector3f = rsurface.modelsvector3f;
6101 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6102 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6103 rsurface.tvector3f = rsurface.modeltvector3f;
6104 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6105 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6106 rsurface.normal3f = rsurface.modelnormal3f;
6107 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6108 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6109 // if vertices are deformed (sprite flares and things in maps, possibly
6110 // water waves, bulges and other deformations), generate them into
6111 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6112 // (may be static model data or generated data for an animated model, or
6113 // the previous deform pass)
6114 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6116 switch (deform->deform)
6119 case Q3DEFORM_PROJECTIONSHADOW:
6120 case Q3DEFORM_TEXT0:
6121 case Q3DEFORM_TEXT1:
6122 case Q3DEFORM_TEXT2:
6123 case Q3DEFORM_TEXT3:
6124 case Q3DEFORM_TEXT4:
6125 case Q3DEFORM_TEXT5:
6126 case Q3DEFORM_TEXT6:
6127 case Q3DEFORM_TEXT7:
6130 case Q3DEFORM_AUTOSPRITE:
6131 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6132 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6133 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6134 VectorNormalize(newforward);
6135 VectorNormalize(newright);
6136 VectorNormalize(newup);
6137 // make deformed versions of only the model vertices used by the specified surfaces
6138 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6140 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6141 // a single autosprite surface can contain multiple sprites...
6142 for (j = 0;j < surface->num_vertices - 3;j += 4)
6144 VectorClear(center);
6145 for (i = 0;i < 4;i++)
6146 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6147 VectorScale(center, 0.25f, center);
6148 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6149 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6150 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6151 for (i = 0;i < 4;i++)
6153 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6154 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6157 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);
6158 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);
6160 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6161 rsurface.vertex3f_bufferobject = 0;
6162 rsurface.vertex3f_bufferoffset = 0;
6163 rsurface.svector3f = rsurface.array_deformedsvector3f;
6164 rsurface.svector3f_bufferobject = 0;
6165 rsurface.svector3f_bufferoffset = 0;
6166 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6167 rsurface.tvector3f_bufferobject = 0;
6168 rsurface.tvector3f_bufferoffset = 0;
6169 rsurface.normal3f = rsurface.array_deformednormal3f;
6170 rsurface.normal3f_bufferobject = 0;
6171 rsurface.normal3f_bufferoffset = 0;
6173 case Q3DEFORM_AUTOSPRITE2:
6174 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6175 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6176 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6177 VectorNormalize(newforward);
6178 VectorNormalize(newright);
6179 VectorNormalize(newup);
6180 // make deformed versions of only the model vertices used by the specified surfaces
6181 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6183 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6184 const float *v1, *v2;
6194 memset(shortest, 0, sizeof(shortest));
6195 // a single autosprite surface can contain multiple sprites...
6196 for (j = 0;j < surface->num_vertices - 3;j += 4)
6198 VectorClear(center);
6199 for (i = 0;i < 4;i++)
6200 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6201 VectorScale(center, 0.25f, center);
6202 // find the two shortest edges, then use them to define the
6203 // axis vectors for rotating around the central axis
6204 for (i = 0;i < 6;i++)
6206 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6207 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6209 Debug_PolygonBegin(NULL, 0);
6210 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6211 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);
6212 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6215 l = VectorDistance2(v1, v2);
6216 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6218 l += (1.0f / 1024.0f);
6219 if (shortest[0].length2 > l || i == 0)
6221 shortest[1] = shortest[0];
6222 shortest[0].length2 = l;
6223 shortest[0].v1 = v1;
6224 shortest[0].v2 = v2;
6226 else if (shortest[1].length2 > l || i == 1)
6228 shortest[1].length2 = l;
6229 shortest[1].v1 = v1;
6230 shortest[1].v2 = v2;
6233 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6234 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6236 Debug_PolygonBegin(NULL, 0);
6237 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6238 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);
6239 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6242 // this calculates the right vector from the shortest edge
6243 // and the up vector from the edge midpoints
6244 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6245 VectorNormalize(right);
6246 VectorSubtract(end, start, up);
6247 VectorNormalize(up);
6248 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6249 VectorSubtract(rsurface.localvieworigin, center, forward);
6250 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6251 VectorNegate(forward, forward);
6252 VectorReflect(forward, 0, up, forward);
6253 VectorNormalize(forward);
6254 CrossProduct(up, forward, newright);
6255 VectorNormalize(newright);
6257 Debug_PolygonBegin(NULL, 0);
6258 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);
6259 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6260 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6264 Debug_PolygonBegin(NULL, 0);
6265 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6266 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6267 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6270 // rotate the quad around the up axis vector, this is made
6271 // especially easy by the fact we know the quad is flat,
6272 // so we only have to subtract the center position and
6273 // measure distance along the right vector, and then
6274 // multiply that by the newright vector and add back the
6276 // we also need to subtract the old position to undo the
6277 // displacement from the center, which we do with a
6278 // DotProduct, the subtraction/addition of center is also
6279 // optimized into DotProducts here
6280 l = DotProduct(right, center);
6281 for (i = 0;i < 4;i++)
6283 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6284 f = DotProduct(right, v1) - l;
6285 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6288 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);
6289 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);
6291 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6292 rsurface.vertex3f_bufferobject = 0;
6293 rsurface.vertex3f_bufferoffset = 0;
6294 rsurface.svector3f = rsurface.array_deformedsvector3f;
6295 rsurface.svector3f_bufferobject = 0;
6296 rsurface.svector3f_bufferoffset = 0;
6297 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6298 rsurface.tvector3f_bufferobject = 0;
6299 rsurface.tvector3f_bufferoffset = 0;
6300 rsurface.normal3f = rsurface.array_deformednormal3f;
6301 rsurface.normal3f_bufferobject = 0;
6302 rsurface.normal3f_bufferoffset = 0;
6304 case Q3DEFORM_NORMAL:
6305 // deform the normals to make reflections wavey
6306 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6308 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6309 for (j = 0;j < surface->num_vertices;j++)
6312 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6313 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6314 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6315 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6316 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6317 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6318 VectorNormalize(normal);
6320 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);
6322 rsurface.svector3f = rsurface.array_deformedsvector3f;
6323 rsurface.svector3f_bufferobject = 0;
6324 rsurface.svector3f_bufferoffset = 0;
6325 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6326 rsurface.tvector3f_bufferobject = 0;
6327 rsurface.tvector3f_bufferoffset = 0;
6328 rsurface.normal3f = rsurface.array_deformednormal3f;
6329 rsurface.normal3f_bufferobject = 0;
6330 rsurface.normal3f_bufferoffset = 0;
6333 // deform vertex array to make wavey water and flags and such
6334 waveparms[0] = deform->waveparms[0];
6335 waveparms[1] = deform->waveparms[1];
6336 waveparms[2] = deform->waveparms[2];
6337 waveparms[3] = deform->waveparms[3];
6338 // this is how a divisor of vertex influence on deformation
6339 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6340 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6341 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6343 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6344 for (j = 0;j < surface->num_vertices;j++)
6346 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6347 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6348 // if the wavefunc depends on time, evaluate it per-vertex
6351 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6352 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6354 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6357 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6358 rsurface.vertex3f_bufferobject = 0;
6359 rsurface.vertex3f_bufferoffset = 0;
6361 case Q3DEFORM_BULGE:
6362 // deform vertex array to make the surface have moving bulges
6363 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6365 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6366 for (j = 0;j < surface->num_vertices;j++)
6368 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6369 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6372 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6373 rsurface.vertex3f_bufferobject = 0;
6374 rsurface.vertex3f_bufferoffset = 0;
6377 // deform vertex array
6378 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6379 VectorScale(deform->parms, scale, waveparms);
6380 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6382 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6383 for (j = 0;j < surface->num_vertices;j++)
6384 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6386 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6387 rsurface.vertex3f_bufferobject = 0;
6388 rsurface.vertex3f_bufferoffset = 0;
6392 // generate texcoords based on the chosen texcoord source
6393 switch(rsurface.texture->tcgen.tcgen)
6396 case Q3TCGEN_TEXTURE:
6397 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6398 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6399 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6401 case Q3TCGEN_LIGHTMAP:
6402 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6403 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6404 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6406 case Q3TCGEN_VECTOR:
6407 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6409 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6410 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)
6412 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6413 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6416 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6417 rsurface.texcoordtexture2f_bufferobject = 0;
6418 rsurface.texcoordtexture2f_bufferoffset = 0;
6420 case Q3TCGEN_ENVIRONMENT:
6421 // make environment reflections using a spheremap
6422 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6424 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6425 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6426 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6427 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6428 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6430 // identical to Q3A's method, but executed in worldspace so
6431 // carried models can be shiny too
6433 float viewer[3], d, reflected[3], worldreflected[3];
6435 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6436 // VectorNormalize(viewer);
6438 d = DotProduct(normal, viewer);
6440 reflected[0] = normal[0]*2*d - viewer[0];
6441 reflected[1] = normal[1]*2*d - viewer[1];
6442 reflected[2] = normal[2]*2*d - viewer[2];
6443 // note: this is proportinal to viewer, so we can normalize later
6445 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6446 VectorNormalize(worldreflected);
6448 // note: this sphere map only uses world x and z!
6449 // so positive and negative y will LOOK THE SAME.
6450 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6451 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6454 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6455 rsurface.texcoordtexture2f_bufferobject = 0;
6456 rsurface.texcoordtexture2f_bufferoffset = 0;
6459 // the only tcmod that needs software vertex processing is turbulent, so
6460 // check for it here and apply the changes if needed
6461 // and we only support that as the first one
6462 // (handling a mixture of turbulent and other tcmods would be problematic
6463 // without punting it entirely to a software path)
6464 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6466 amplitude = rsurface.texture->tcmods[0].parms[1];
6467 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6468 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6470 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6471 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)
6473 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6474 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6477 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6478 rsurface.texcoordtexture2f_bufferobject = 0;
6479 rsurface.texcoordtexture2f_bufferoffset = 0;
6481 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6482 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6483 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6484 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6487 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6490 const msurface_t *surface = texturesurfacelist[0];
6491 const msurface_t *surface2;
6496 // TODO: lock all array ranges before render, rather than on each surface
6497 if (texturenumsurfaces == 1)
6499 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6500 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);
6502 else if (r_batchmode.integer == 2)
6504 #define MAXBATCHTRIANGLES 4096
6505 int batchtriangles = 0;
6506 int batchelements[MAXBATCHTRIANGLES*3];
6507 for (i = 0;i < texturenumsurfaces;i = j)
6509 surface = texturesurfacelist[i];
6511 if (surface->num_triangles > MAXBATCHTRIANGLES)
6513 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);
6516 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6517 batchtriangles = surface->num_triangles;
6518 firstvertex = surface->num_firstvertex;
6519 endvertex = surface->num_firstvertex + surface->num_vertices;
6520 for (;j < texturenumsurfaces;j++)
6522 surface2 = texturesurfacelist[j];
6523 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6525 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6526 batchtriangles += surface2->num_triangles;
6527 firstvertex = min(firstvertex, surface2->num_firstvertex);
6528 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6530 surface2 = texturesurfacelist[j-1];
6531 numvertices = endvertex - firstvertex;
6532 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6535 else if (r_batchmode.integer == 1)
6537 for (i = 0;i < texturenumsurfaces;i = j)
6539 surface = texturesurfacelist[i];
6540 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6541 if (texturesurfacelist[j] != surface2)
6543 surface2 = texturesurfacelist[j-1];
6544 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6545 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6546 GL_LockArrays(surface->num_firstvertex, numvertices);
6547 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6552 for (i = 0;i < texturenumsurfaces;i++)
6554 surface = texturesurfacelist[i];
6555 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6556 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);
6561 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6563 int i, planeindex, vertexindex;
6567 r_waterstate_waterplane_t *p, *bestp;
6568 msurface_t *surface;
6569 if (r_waterstate.renderingscene)
6571 for (i = 0;i < texturenumsurfaces;i++)
6573 surface = texturesurfacelist[i];
6574 if (lightmaptexunit >= 0)
6575 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6576 if (deluxemaptexunit >= 0)
6577 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6578 // pick the closest matching water plane
6581 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6584 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6586 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6587 d += fabs(PlaneDiff(vert, &p->plane));
6589 if (bestd > d || !bestp)
6597 if (refractiontexunit >= 0)
6598 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6599 if (reflectiontexunit >= 0)
6600 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6604 if (refractiontexunit >= 0)
6605 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6606 if (reflectiontexunit >= 0)
6607 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6609 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6610 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);
6614 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6618 const msurface_t *surface = texturesurfacelist[0];
6619 const msurface_t *surface2;
6624 // TODO: lock all array ranges before render, rather than on each surface
6625 if (texturenumsurfaces == 1)
6627 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6628 if (deluxemaptexunit >= 0)
6629 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6630 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6631 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);
6633 else if (r_batchmode.integer == 2)
6635 #define MAXBATCHTRIANGLES 4096
6636 int batchtriangles = 0;
6637 int batchelements[MAXBATCHTRIANGLES*3];
6638 for (i = 0;i < texturenumsurfaces;i = j)
6640 surface = texturesurfacelist[i];
6641 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6642 if (deluxemaptexunit >= 0)
6643 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6645 if (surface->num_triangles > MAXBATCHTRIANGLES)
6647 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);
6650 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6651 batchtriangles = surface->num_triangles;
6652 firstvertex = surface->num_firstvertex;
6653 endvertex = surface->num_firstvertex + surface->num_vertices;
6654 for (;j < texturenumsurfaces;j++)
6656 surface2 = texturesurfacelist[j];
6657 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6659 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6660 batchtriangles += surface2->num_triangles;
6661 firstvertex = min(firstvertex, surface2->num_firstvertex);
6662 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6664 surface2 = texturesurfacelist[j-1];
6665 numvertices = endvertex - firstvertex;
6666 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6669 else if (r_batchmode.integer == 1)
6672 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6673 for (i = 0;i < texturenumsurfaces;i = j)
6675 surface = texturesurfacelist[i];
6676 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6677 if (texturesurfacelist[j] != surface2)
6679 Con_Printf(" %i", j - i);
6682 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6684 for (i = 0;i < texturenumsurfaces;i = j)
6686 surface = texturesurfacelist[i];
6687 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6688 if (deluxemaptexunit >= 0)
6689 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6690 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6691 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6694 Con_Printf(" %i", j - i);
6696 surface2 = texturesurfacelist[j-1];
6697 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6698 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6699 GL_LockArrays(surface->num_firstvertex, numvertices);
6700 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6708 for (i = 0;i < texturenumsurfaces;i++)
6710 surface = texturesurfacelist[i];
6711 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6712 if (deluxemaptexunit >= 0)
6713 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6714 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6715 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);
6720 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6723 int texturesurfaceindex;
6724 if (r_showsurfaces.integer == 2)
6726 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6728 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6729 for (j = 0;j < surface->num_triangles;j++)
6731 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6732 GL_Color(f, f, f, 1);
6733 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6739 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6741 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6742 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6743 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);
6744 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6745 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);
6750 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6752 int texturesurfaceindex;
6755 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6757 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6758 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)
6766 rsurface.lightmapcolor4f = rsurface.array_color4f;
6767 rsurface.lightmapcolor4f_bufferobject = 0;
6768 rsurface.lightmapcolor4f_bufferoffset = 0;
6771 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6773 int texturesurfaceindex;
6777 if (rsurface.lightmapcolor4f)
6779 // generate color arrays for the surfaces in this list
6780 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6782 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6783 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)
6785 f = RSurf_FogVertex(v);
6795 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6797 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6798 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)
6800 f = RSurf_FogVertex(v);
6808 rsurface.lightmapcolor4f = rsurface.array_color4f;
6809 rsurface.lightmapcolor4f_bufferobject = 0;
6810 rsurface.lightmapcolor4f_bufferoffset = 0;
6813 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6815 int texturesurfaceindex;
6819 if (!rsurface.lightmapcolor4f)
6821 // generate color arrays for the surfaces in this list
6822 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6824 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6825 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)
6827 f = RSurf_FogVertex(v);
6828 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6829 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6830 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6834 rsurface.lightmapcolor4f = rsurface.array_color4f;
6835 rsurface.lightmapcolor4f_bufferobject = 0;
6836 rsurface.lightmapcolor4f_bufferoffset = 0;
6839 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6841 int texturesurfaceindex;
6844 if (!rsurface.lightmapcolor4f)
6846 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6848 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6849 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)
6857 rsurface.lightmapcolor4f = rsurface.array_color4f;
6858 rsurface.lightmapcolor4f_bufferobject = 0;
6859 rsurface.lightmapcolor4f_bufferoffset = 0;
6862 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6864 int texturesurfaceindex;
6867 if (!rsurface.lightmapcolor4f)
6869 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6871 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6872 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)
6874 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6875 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6876 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6880 rsurface.lightmapcolor4f = rsurface.array_color4f;
6881 rsurface.lightmapcolor4f_bufferobject = 0;
6882 rsurface.lightmapcolor4f_bufferoffset = 0;
6885 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6888 rsurface.lightmapcolor4f = NULL;
6889 rsurface.lightmapcolor4f_bufferobject = 0;
6890 rsurface.lightmapcolor4f_bufferoffset = 0;
6891 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6892 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6893 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6894 GL_Color(r, g, b, a);
6895 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6898 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6900 // TODO: optimize applyfog && applycolor case
6901 // just apply fog if necessary, and tint the fog color array if necessary
6902 rsurface.lightmapcolor4f = NULL;
6903 rsurface.lightmapcolor4f_bufferobject = 0;
6904 rsurface.lightmapcolor4f_bufferoffset = 0;
6905 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6906 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6907 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6908 GL_Color(r, g, b, a);
6909 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6912 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6914 int texturesurfaceindex;
6918 if (texturesurfacelist[0]->lightmapinfo)
6920 // generate color arrays for the surfaces in this list
6921 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6923 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6924 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6926 if (surface->lightmapinfo->samples)
6928 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6929 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6930 VectorScale(lm, scale, c);
6931 if (surface->lightmapinfo->styles[1] != 255)
6933 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6935 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6936 VectorMA(c, scale, lm, c);
6937 if (surface->lightmapinfo->styles[2] != 255)
6940 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6941 VectorMA(c, scale, lm, c);
6942 if (surface->lightmapinfo->styles[3] != 255)
6945 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6946 VectorMA(c, scale, lm, c);
6956 rsurface.lightmapcolor4f = rsurface.array_color4f;
6957 rsurface.lightmapcolor4f_bufferobject = 0;
6958 rsurface.lightmapcolor4f_bufferoffset = 0;
6962 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6963 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6964 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6966 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6967 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6968 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6969 GL_Color(r, g, b, a);
6970 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6973 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6975 int texturesurfaceindex;
6978 float *v, *c, *c2, alpha;
6979 vec3_t ambientcolor;
6980 vec3_t diffusecolor;
6984 VectorCopy(rsurface.modellight_lightdir, lightdir);
6985 f = 0.5f * r_refdef.lightmapintensity;
6986 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6987 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6988 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6989 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6990 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6991 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6993 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6995 // generate color arrays for the surfaces in this list
6996 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6998 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6999 int numverts = surface->num_vertices;
7000 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7001 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
7002 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7003 // q3-style directional shading
7004 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
7006 if ((f = DotProduct(c2, lightdir)) > 0)
7007 VectorMA(ambientcolor, f, diffusecolor, c);
7009 VectorCopy(ambientcolor, c);
7017 rsurface.lightmapcolor4f = rsurface.array_color4f;
7018 rsurface.lightmapcolor4f_bufferobject = 0;
7019 rsurface.lightmapcolor4f_bufferoffset = 0;
7020 *applycolor = false;
7024 *r = ambientcolor[0];
7025 *g = ambientcolor[1];
7026 *b = ambientcolor[2];
7027 rsurface.lightmapcolor4f = NULL;
7028 rsurface.lightmapcolor4f_bufferobject = 0;
7029 rsurface.lightmapcolor4f_bufferoffset = 0;
7033 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7035 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7036 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7037 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7038 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7039 GL_Color(r, g, b, a);
7040 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7043 void RSurf_SetupDepthAndCulling(void)
7045 // submodels are biased to avoid z-fighting with world surfaces that they
7046 // may be exactly overlapping (avoids z-fighting artifacts on certain
7047 // doors and things in Quake maps)
7048 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7049 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7050 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7051 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7054 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
7056 // transparent sky would be ridiculous
7057 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7059 R_SetupGenericShader(false);
7060 skyrenderlater = true;
7061 RSurf_SetupDepthAndCulling();
7063 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7064 // skymasking on them, and Quake3 never did sky masking (unlike
7065 // software Quake and software Quake2), so disable the sky masking
7066 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7067 // and skymasking also looks very bad when noclipping outside the
7068 // level, so don't use it then either.
7069 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7071 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7072 R_Mesh_ColorPointer(NULL, 0, 0);
7073 R_Mesh_ResetTextureState();
7074 if (skyrendermasked)
7076 R_SetupDepthOrShadowShader();
7077 // depth-only (masking)
7078 GL_ColorMask(0,0,0,0);
7079 // just to make sure that braindead drivers don't draw
7080 // anything despite that colormask...
7081 GL_BlendFunc(GL_ZERO, GL_ONE);
7085 R_SetupGenericShader(false);
7087 GL_BlendFunc(GL_ONE, GL_ZERO);
7089 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7090 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7091 if (skyrendermasked)
7092 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7094 R_Mesh_ResetTextureState();
7095 GL_Color(1, 1, 1, 1);
7098 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7100 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7103 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7104 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7105 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7106 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7107 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7108 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7109 if (rsurface.texture->backgroundcurrentskinframe)
7111 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7112 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7113 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7114 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7116 if(rsurface.texture->colormapping)
7118 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7119 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7121 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7122 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7123 R_Mesh_ColorPointer(NULL, 0, 0);
7125 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7127 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7129 // render background
7130 GL_BlendFunc(GL_ONE, GL_ZERO);
7132 GL_AlphaTest(false);
7134 GL_Color(1, 1, 1, 1);
7135 R_Mesh_ColorPointer(NULL, 0, 0);
7137 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7138 if (r_glsl_permutation)
7140 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7141 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7142 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7143 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7144 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7145 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7146 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);
7148 GL_LockArrays(0, 0);
7150 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7151 GL_DepthMask(false);
7152 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7153 R_Mesh_ColorPointer(NULL, 0, 0);
7155 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7156 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7157 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7160 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7161 if (!r_glsl_permutation)
7164 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7165 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7166 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7167 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7168 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7169 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7171 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7173 GL_BlendFunc(GL_ONE, GL_ZERO);
7175 GL_AlphaTest(false);
7179 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7180 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7181 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7184 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7186 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7187 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);
7189 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7193 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7194 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);
7196 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7198 GL_LockArrays(0, 0);
7201 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7203 // OpenGL 1.3 path - anything not completely ancient
7204 int texturesurfaceindex;
7205 qboolean applycolor;
7209 const texturelayer_t *layer;
7210 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7212 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7215 int layertexrgbscale;
7216 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7218 if (layerindex == 0)
7222 GL_AlphaTest(false);
7223 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7226 GL_DepthMask(layer->depthmask && writedepth);
7227 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7228 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7230 layertexrgbscale = 4;
7231 VectorScale(layer->color, 0.25f, layercolor);
7233 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7235 layertexrgbscale = 2;
7236 VectorScale(layer->color, 0.5f, layercolor);
7240 layertexrgbscale = 1;
7241 VectorScale(layer->color, 1.0f, layercolor);
7243 layercolor[3] = layer->color[3];
7244 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7245 R_Mesh_ColorPointer(NULL, 0, 0);
7246 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7247 switch (layer->type)
7249 case TEXTURELAYERTYPE_LITTEXTURE:
7250 memset(&m, 0, sizeof(m));
7251 m.tex[0] = R_GetTexture(r_texture_white);
7252 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7253 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7254 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7255 m.tex[1] = R_GetTexture(layer->texture);
7256 m.texmatrix[1] = layer->texmatrix;
7257 m.texrgbscale[1] = layertexrgbscale;
7258 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7259 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7260 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7261 R_Mesh_TextureState(&m);
7262 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7263 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7264 else if (rsurface.uselightmaptexture)
7265 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7267 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7269 case TEXTURELAYERTYPE_TEXTURE:
7270 memset(&m, 0, sizeof(m));
7271 m.tex[0] = R_GetTexture(layer->texture);
7272 m.texmatrix[0] = layer->texmatrix;
7273 m.texrgbscale[0] = layertexrgbscale;
7274 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7275 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7276 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7277 R_Mesh_TextureState(&m);
7278 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7280 case TEXTURELAYERTYPE_FOG:
7281 memset(&m, 0, sizeof(m));
7282 m.texrgbscale[0] = layertexrgbscale;
7285 m.tex[0] = R_GetTexture(layer->texture);
7286 m.texmatrix[0] = layer->texmatrix;
7287 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7288 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7289 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7291 R_Mesh_TextureState(&m);
7292 // generate a color array for the fog pass
7293 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7294 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7298 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7299 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)
7301 f = 1 - RSurf_FogVertex(v);
7302 c[0] = layercolor[0];
7303 c[1] = layercolor[1];
7304 c[2] = layercolor[2];
7305 c[3] = f * layercolor[3];
7308 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7311 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7313 GL_LockArrays(0, 0);
7316 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7318 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7319 GL_AlphaTest(false);
7323 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7325 // OpenGL 1.1 - crusty old voodoo path
7326 int texturesurfaceindex;
7330 const texturelayer_t *layer;
7331 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7333 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7335 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7337 if (layerindex == 0)
7341 GL_AlphaTest(false);
7342 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7345 GL_DepthMask(layer->depthmask && writedepth);
7346 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7347 R_Mesh_ColorPointer(NULL, 0, 0);
7348 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7349 switch (layer->type)
7351 case TEXTURELAYERTYPE_LITTEXTURE:
7352 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7354 // two-pass lit texture with 2x rgbscale
7355 // first the lightmap pass
7356 memset(&m, 0, sizeof(m));
7357 m.tex[0] = R_GetTexture(r_texture_white);
7358 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7359 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7360 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7361 R_Mesh_TextureState(&m);
7362 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7363 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7364 else if (rsurface.uselightmaptexture)
7365 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7367 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7368 GL_LockArrays(0, 0);
7369 // then apply the texture to it
7370 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7371 memset(&m, 0, sizeof(m));
7372 m.tex[0] = R_GetTexture(layer->texture);
7373 m.texmatrix[0] = layer->texmatrix;
7374 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7375 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7376 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7377 R_Mesh_TextureState(&m);
7378 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);
7382 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7383 memset(&m, 0, sizeof(m));
7384 m.tex[0] = R_GetTexture(layer->texture);
7385 m.texmatrix[0] = layer->texmatrix;
7386 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7387 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7388 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7389 R_Mesh_TextureState(&m);
7390 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7391 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);
7393 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);
7396 case TEXTURELAYERTYPE_TEXTURE:
7397 // singletexture unlit texture with transparency support
7398 memset(&m, 0, sizeof(m));
7399 m.tex[0] = R_GetTexture(layer->texture);
7400 m.texmatrix[0] = layer->texmatrix;
7401 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7402 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7403 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7404 R_Mesh_TextureState(&m);
7405 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);
7407 case TEXTURELAYERTYPE_FOG:
7408 // singletexture fogging
7409 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7412 memset(&m, 0, sizeof(m));
7413 m.tex[0] = R_GetTexture(layer->texture);
7414 m.texmatrix[0] = layer->texmatrix;
7415 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7416 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7417 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7418 R_Mesh_TextureState(&m);
7421 R_Mesh_ResetTextureState();
7422 // generate a color array for the fog pass
7423 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7427 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7428 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)
7430 f = 1 - RSurf_FogVertex(v);
7431 c[0] = layer->color[0];
7432 c[1] = layer->color[1];
7433 c[2] = layer->color[2];
7434 c[3] = f * layer->color[3];
7437 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7440 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7442 GL_LockArrays(0, 0);
7445 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7447 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7448 GL_AlphaTest(false);
7452 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7456 GL_AlphaTest(false);
7457 R_Mesh_ColorPointer(NULL, 0, 0);
7458 R_Mesh_ResetTextureState();
7459 R_SetupGenericShader(false);
7461 if(rsurface.texture && rsurface.texture->currentskinframe)
7463 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7464 c[3] *= rsurface.texture->currentalpha;
7474 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7476 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7477 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7478 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7481 // brighten it up (as texture value 127 means "unlit")
7482 c[0] *= 2 * r_refdef.view.colorscale;
7483 c[1] *= 2 * r_refdef.view.colorscale;
7484 c[2] *= 2 * r_refdef.view.colorscale;
7486 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7487 c[3] *= r_wateralpha.value;
7489 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7491 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7492 GL_DepthMask(false);
7494 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7496 GL_BlendFunc(GL_ONE, GL_ONE);
7497 GL_DepthMask(false);
7499 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7501 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7502 GL_DepthMask(false);
7504 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7506 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7507 GL_DepthMask(false);
7511 GL_BlendFunc(GL_ONE, GL_ZERO);
7512 GL_DepthMask(writedepth);
7515 rsurface.lightmapcolor4f = NULL;
7517 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7519 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7521 rsurface.lightmapcolor4f = NULL;
7522 rsurface.lightmapcolor4f_bufferobject = 0;
7523 rsurface.lightmapcolor4f_bufferoffset = 0;
7525 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7527 qboolean applycolor = true;
7530 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7532 r_refdef.lightmapintensity = 1;
7533 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7534 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7538 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7540 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7541 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7542 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7545 if(!rsurface.lightmapcolor4f)
7546 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7548 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7549 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7550 if(r_refdef.fogenabled)
7551 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7553 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7554 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7557 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7560 RSurf_SetupDepthAndCulling();
7561 if (r_showsurfaces.integer == 3)
7562 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7563 else if (r_glsl.integer && gl_support_fragment_shader)
7564 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7565 else if (gl_combine.integer && r_textureunits.integer >= 2)
7566 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7568 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7572 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7575 RSurf_SetupDepthAndCulling();
7576 if (r_showsurfaces.integer == 3)
7577 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7578 else if (r_glsl.integer && gl_support_fragment_shader)
7579 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7580 else if (gl_combine.integer && r_textureunits.integer >= 2)
7581 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7583 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7587 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7590 int texturenumsurfaces, endsurface;
7592 msurface_t *surface;
7593 msurface_t *texturesurfacelist[1024];
7595 // if the model is static it doesn't matter what value we give for
7596 // wantnormals and wanttangents, so this logic uses only rules applicable
7597 // to a model, knowing that they are meaningless otherwise
7598 if (ent == r_refdef.scene.worldentity)
7599 RSurf_ActiveWorldEntity();
7600 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7601 RSurf_ActiveModelEntity(ent, false, false);
7603 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7605 for (i = 0;i < numsurfaces;i = j)
7608 surface = rsurface.modelsurfaces + surfacelist[i];
7609 texture = surface->texture;
7610 rsurface.texture = R_GetCurrentTexture(texture);
7611 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7612 // scan ahead until we find a different texture
7613 endsurface = min(i + 1024, numsurfaces);
7614 texturenumsurfaces = 0;
7615 texturesurfacelist[texturenumsurfaces++] = surface;
7616 for (;j < endsurface;j++)
7618 surface = rsurface.modelsurfaces + surfacelist[j];
7619 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7621 texturesurfacelist[texturenumsurfaces++] = surface;
7623 // render the range of surfaces
7624 if (ent == r_refdef.scene.worldentity)
7625 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7627 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7629 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7630 GL_AlphaTest(false);
7633 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7635 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7639 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7641 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7643 RSurf_SetupDepthAndCulling();
7644 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7645 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7647 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7649 RSurf_SetupDepthAndCulling();
7650 GL_AlphaTest(false);
7651 R_Mesh_ColorPointer(NULL, 0, 0);
7652 R_Mesh_ResetTextureState();
7653 R_SetupGenericShader(false);
7654 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7656 GL_BlendFunc(GL_ONE, GL_ZERO);
7657 GL_Color(0, 0, 0, 1);
7658 GL_DepthTest(writedepth);
7659 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7661 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7663 RSurf_SetupDepthAndCulling();
7664 GL_AlphaTest(false);
7665 R_Mesh_ColorPointer(NULL, 0, 0);
7666 R_Mesh_ResetTextureState();
7667 R_SetupGenericShader(false);
7668 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7670 GL_BlendFunc(GL_ONE, GL_ZERO);
7672 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7674 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7675 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7676 else if (!rsurface.texture->currentnumlayers)
7678 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7680 // transparent surfaces get pushed off into the transparent queue
7681 int surfacelistindex;
7682 const msurface_t *surface;
7683 vec3_t tempcenter, center;
7684 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7686 surface = texturesurfacelist[surfacelistindex];
7687 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7688 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7689 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7690 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7691 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7696 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7697 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7702 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7706 // break the surface list down into batches by texture and use of lightmapping
7707 for (i = 0;i < numsurfaces;i = j)
7710 // texture is the base texture pointer, rsurface.texture is the
7711 // current frame/skin the texture is directing us to use (for example
7712 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7713 // use skin 1 instead)
7714 texture = surfacelist[i]->texture;
7715 rsurface.texture = R_GetCurrentTexture(texture);
7716 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7717 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7719 // if this texture is not the kind we want, skip ahead to the next one
7720 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7724 // simply scan ahead until we find a different texture or lightmap state
7725 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7727 // render the range of surfaces
7728 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7732 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7737 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7739 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7741 RSurf_SetupDepthAndCulling();
7742 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7743 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7745 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7747 RSurf_SetupDepthAndCulling();
7748 GL_AlphaTest(false);
7749 R_Mesh_ColorPointer(NULL, 0, 0);
7750 R_Mesh_ResetTextureState();
7751 R_SetupGenericShader(false);
7752 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7754 GL_BlendFunc(GL_ONE, GL_ZERO);
7755 GL_Color(0, 0, 0, 1);
7756 GL_DepthTest(writedepth);
7757 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7759 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7761 RSurf_SetupDepthAndCulling();
7762 GL_AlphaTest(false);
7763 R_Mesh_ColorPointer(NULL, 0, 0);
7764 R_Mesh_ResetTextureState();
7765 R_SetupGenericShader(false);
7766 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7768 GL_BlendFunc(GL_ONE, GL_ZERO);
7770 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7772 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7773 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7774 else if (!rsurface.texture->currentnumlayers)
7776 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7778 // transparent surfaces get pushed off into the transparent queue
7779 int surfacelistindex;
7780 const msurface_t *surface;
7781 vec3_t tempcenter, center;
7782 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7784 surface = texturesurfacelist[surfacelistindex];
7785 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7786 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7787 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7788 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7789 if (queueentity->transparent_offset) // transparent offset
7791 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
7792 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
7793 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
7795 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7800 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7801 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7806 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7810 // break the surface list down into batches by texture and use of lightmapping
7811 for (i = 0;i < numsurfaces;i = j)
7814 // texture is the base texture pointer, rsurface.texture is the
7815 // current frame/skin the texture is directing us to use (for example
7816 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7817 // use skin 1 instead)
7818 texture = surfacelist[i]->texture;
7819 rsurface.texture = R_GetCurrentTexture(texture);
7820 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7821 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7823 // if this texture is not the kind we want, skip ahead to the next one
7824 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7828 // simply scan ahead until we find a different texture or lightmap state
7829 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7831 // render the range of surfaces
7832 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7836 float locboxvertex3f[6*4*3] =
7838 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7839 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7840 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7841 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7842 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7843 1,0,0, 0,0,0, 0,1,0, 1,1,0
7846 unsigned short locboxelements[6*2*3] =
7856 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7859 cl_locnode_t *loc = (cl_locnode_t *)ent;
7861 float vertex3f[6*4*3];
7863 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7864 GL_DepthMask(false);
7865 GL_DepthRange(0, 1);
7866 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7868 GL_CullFace(GL_NONE);
7869 R_Mesh_Matrix(&identitymatrix);
7871 R_Mesh_VertexPointer(vertex3f, 0, 0);
7872 R_Mesh_ColorPointer(NULL, 0, 0);
7873 R_Mesh_ResetTextureState();
7874 R_SetupGenericShader(false);
7877 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7878 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7879 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7880 surfacelist[0] < 0 ? 0.5f : 0.125f);
7882 if (VectorCompare(loc->mins, loc->maxs))
7884 VectorSet(size, 2, 2, 2);
7885 VectorMA(loc->mins, -0.5f, size, mins);
7889 VectorCopy(loc->mins, mins);
7890 VectorSubtract(loc->maxs, loc->mins, size);
7893 for (i = 0;i < 6*4*3;)
7894 for (j = 0;j < 3;j++, i++)
7895 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7897 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7900 void R_DrawLocs(void)
7903 cl_locnode_t *loc, *nearestloc;
7905 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7906 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7908 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7909 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7913 void R_DrawDebugModel(entity_render_t *ent)
7915 int i, j, k, l, flagsmask;
7916 const int *elements;
7918 msurface_t *surface;
7919 dp_model_t *model = ent->model;
7922 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7924 R_Mesh_ColorPointer(NULL, 0, 0);
7925 R_Mesh_ResetTextureState();
7926 R_SetupGenericShader(false);
7927 GL_DepthRange(0, 1);
7928 GL_DepthTest(!r_showdisabledepthtest.integer);
7929 GL_DepthMask(false);
7930 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7932 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7934 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7935 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7937 if (brush->colbrushf && brush->colbrushf->numtriangles)
7939 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7940 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);
7941 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7944 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7946 if (surface->num_collisiontriangles)
7948 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7949 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);
7950 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7955 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7957 if (r_showtris.integer || r_shownormals.integer)
7959 if (r_showdisabledepthtest.integer)
7961 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7962 GL_DepthMask(false);
7966 GL_BlendFunc(GL_ONE, GL_ZERO);
7969 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7971 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7973 rsurface.texture = R_GetCurrentTexture(surface->texture);
7974 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7976 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7977 if (r_showtris.value > 0)
7979 if (!rsurface.texture->currentlayers->depthmask)
7980 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7981 else if (ent == r_refdef.scene.worldentity)
7982 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7984 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7985 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7986 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7987 R_Mesh_ColorPointer(NULL, 0, 0);
7988 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7989 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7990 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7991 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);
7992 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7995 if (r_shownormals.value < 0)
7998 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8000 VectorCopy(rsurface.vertex3f + l * 3, v);
8001 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8002 qglVertex3f(v[0], v[1], v[2]);
8003 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8004 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8005 qglVertex3f(v[0], v[1], v[2]);
8010 if (r_shownormals.value > 0)
8013 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8015 VectorCopy(rsurface.vertex3f + l * 3, v);
8016 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8017 qglVertex3f(v[0], v[1], v[2]);
8018 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8019 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8020 qglVertex3f(v[0], v[1], v[2]);
8025 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8027 VectorCopy(rsurface.vertex3f + l * 3, v);
8028 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8029 qglVertex3f(v[0], v[1], v[2]);
8030 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8031 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8032 qglVertex3f(v[0], v[1], v[2]);
8037 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8039 VectorCopy(rsurface.vertex3f + l * 3, v);
8040 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8041 qglVertex3f(v[0], v[1], v[2]);
8042 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8043 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8044 qglVertex3f(v[0], v[1], v[2]);
8051 rsurface.texture = NULL;
8055 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8056 int r_maxsurfacelist = 0;
8057 msurface_t **r_surfacelist = NULL;
8058 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8060 int i, j, endj, f, flagsmask;
8062 dp_model_t *model = r_refdef.scene.worldmodel;
8063 msurface_t *surfaces;
8064 unsigned char *update;
8065 int numsurfacelist = 0;
8069 if (r_maxsurfacelist < model->num_surfaces)
8071 r_maxsurfacelist = model->num_surfaces;
8073 Mem_Free(r_surfacelist);
8074 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8077 RSurf_ActiveWorldEntity();
8079 surfaces = model->data_surfaces;
8080 update = model->brushq1.lightmapupdateflags;
8082 // update light styles on this submodel
8083 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8085 model_brush_lightstyleinfo_t *style;
8086 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8088 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8090 int *list = style->surfacelist;
8091 style->value = r_refdef.scene.lightstylevalue[style->style];
8092 for (j = 0;j < style->numsurfaces;j++)
8093 update[list[j]] = true;
8098 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8102 R_DrawDebugModel(r_refdef.scene.worldentity);
8103 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8109 rsurface.uselightmaptexture = false;
8110 rsurface.texture = NULL;
8111 rsurface.rtlight = NULL;
8113 // add visible surfaces to draw list
8114 for (i = 0;i < model->nummodelsurfaces;i++)
8116 j = model->sortedmodelsurfaces[i];
8117 if (r_refdef.viewcache.world_surfacevisible[j])
8118 r_surfacelist[numsurfacelist++] = surfaces + j;
8120 // update lightmaps if needed
8122 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8123 if (r_refdef.viewcache.world_surfacevisible[j])
8125 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8126 // don't do anything if there were no surfaces
8127 if (!numsurfacelist)
8129 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8132 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8133 GL_AlphaTest(false);
8135 // add to stats if desired
8136 if (r_speeds.integer && !skysurfaces && !depthonly)
8138 r_refdef.stats.world_surfaces += numsurfacelist;
8139 for (j = 0;j < numsurfacelist;j++)
8140 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8142 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8145 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8147 int i, j, endj, f, flagsmask;
8149 dp_model_t *model = ent->model;
8150 msurface_t *surfaces;
8151 unsigned char *update;
8152 int numsurfacelist = 0;
8156 if (r_maxsurfacelist < model->num_surfaces)
8158 r_maxsurfacelist = model->num_surfaces;
8160 Mem_Free(r_surfacelist);
8161 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8164 // if the model is static it doesn't matter what value we give for
8165 // wantnormals and wanttangents, so this logic uses only rules applicable
8166 // to a model, knowing that they are meaningless otherwise
8167 if (ent == r_refdef.scene.worldentity)
8168 RSurf_ActiveWorldEntity();
8169 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8170 RSurf_ActiveModelEntity(ent, false, false);
8172 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8174 surfaces = model->data_surfaces;
8175 update = model->brushq1.lightmapupdateflags;
8177 // update light styles
8178 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8180 model_brush_lightstyleinfo_t *style;
8181 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8183 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8185 int *list = style->surfacelist;
8186 style->value = r_refdef.scene.lightstylevalue[style->style];
8187 for (j = 0;j < style->numsurfaces;j++)
8188 update[list[j]] = true;
8193 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8197 R_DrawDebugModel(ent);
8198 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8204 rsurface.uselightmaptexture = false;
8205 rsurface.texture = NULL;
8206 rsurface.rtlight = NULL;
8208 // add visible surfaces to draw list
8209 for (i = 0;i < model->nummodelsurfaces;i++)
8210 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8211 // don't do anything if there were no surfaces
8212 if (!numsurfacelist)
8214 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8217 // update lightmaps if needed
8219 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8221 R_BuildLightMap(ent, surfaces + j);
8222 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8223 GL_AlphaTest(false);
8225 // add to stats if desired
8226 if (r_speeds.integer && !skysurfaces && !depthonly)
8228 r_refdef.stats.entities_surfaces += numsurfacelist;
8229 for (j = 0;j < numsurfacelist;j++)
8230 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8232 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity