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, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
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->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
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->effects & EF_NODEPTHTEST) && !(ent->flags & (RENDER_VIEWMODEL + RENDER_NOCULL)) && !(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);
5035 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5036 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5037 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5038 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5039 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5040 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5041 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5042 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5043 R_FillColors(color4f, 8, cr, cg, cb, ca);
5044 if (r_refdef.fogenabled)
5046 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5048 f1 = RSurf_FogVertex(v);
5050 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5051 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5052 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5055 R_Mesh_VertexPointer(vertex3f, 0, 0);
5056 R_Mesh_ColorPointer(color4f, 0, 0);
5057 R_Mesh_ResetTextureState();
5058 R_SetupGenericShader(false);
5059 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5062 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5066 prvm_edict_t *edict;
5067 prvm_prog_t *prog_save = prog;
5069 // this function draws bounding boxes of server entities
5073 GL_CullFace(GL_NONE);
5074 R_SetupGenericShader(false);
5078 for (i = 0;i < numsurfaces;i++)
5080 edict = PRVM_EDICT_NUM(surfacelist[i]);
5081 switch ((int)edict->fields.server->solid)
5083 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5084 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5085 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5086 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5087 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5088 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5090 color[3] *= r_showbboxes.value;
5091 color[3] = bound(0, color[3], 1);
5092 GL_DepthTest(!r_showdisabledepthtest.integer);
5093 GL_CullFace(r_refdef.view.cullface_front);
5094 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5100 static void R_DrawEntityBBoxes(void)
5103 prvm_edict_t *edict;
5105 prvm_prog_t *prog_save = prog;
5107 // this function draws bounding boxes of server entities
5113 for (i = 0;i < prog->num_edicts;i++)
5115 edict = PRVM_EDICT_NUM(i);
5116 if (edict->priv.server->free)
5118 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5119 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5121 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5123 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5124 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5130 unsigned short nomodelelements[24] =
5142 float nomodelvertex3f[6*3] =
5152 float nomodelcolor4f[6*4] =
5154 0.0f, 0.0f, 0.5f, 1.0f,
5155 0.0f, 0.0f, 0.5f, 1.0f,
5156 0.0f, 0.5f, 0.0f, 1.0f,
5157 0.0f, 0.5f, 0.0f, 1.0f,
5158 0.5f, 0.0f, 0.0f, 1.0f,
5159 0.5f, 0.0f, 0.0f, 1.0f
5162 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5168 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5169 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5171 // this is only called once per entity so numsurfaces is always 1, and
5172 // surfacelist is always {0}, so this code does not handle batches
5173 R_Mesh_Matrix(&ent->matrix);
5175 if (ent->flags & EF_ADDITIVE)
5177 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5178 GL_DepthMask(false);
5180 else if (ent->alpha < 1)
5182 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5183 GL_DepthMask(false);
5187 GL_BlendFunc(GL_ONE, GL_ZERO);
5190 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5191 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5192 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
5193 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5194 R_SetupGenericShader(false);
5195 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
5196 if (r_refdef.fogenabled)
5199 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5200 R_Mesh_ColorPointer(color4f, 0, 0);
5201 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5202 f1 = RSurf_FogVertex(org);
5204 for (i = 0, c = color4f;i < 6;i++, c += 4)
5206 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5207 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5208 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5212 else if (ent->alpha != 1)
5214 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5215 R_Mesh_ColorPointer(color4f, 0, 0);
5216 for (i = 0, c = color4f;i < 6;i++, c += 4)
5220 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
5221 R_Mesh_ResetTextureState();
5222 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
5225 void R_DrawNoModel(entity_render_t *ent)
5228 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5229 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
5230 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5232 // R_DrawNoModelCallback(ent, 0);
5235 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5237 vec3_t right1, right2, diff, normal;
5239 VectorSubtract (org2, org1, normal);
5241 // calculate 'right' vector for start
5242 VectorSubtract (r_refdef.view.origin, org1, diff);
5243 CrossProduct (normal, diff, right1);
5244 VectorNormalize (right1);
5246 // calculate 'right' vector for end
5247 VectorSubtract (r_refdef.view.origin, org2, diff);
5248 CrossProduct (normal, diff, right2);
5249 VectorNormalize (right2);
5251 vert[ 0] = org1[0] + width * right1[0];
5252 vert[ 1] = org1[1] + width * right1[1];
5253 vert[ 2] = org1[2] + width * right1[2];
5254 vert[ 3] = org1[0] - width * right1[0];
5255 vert[ 4] = org1[1] - width * right1[1];
5256 vert[ 5] = org1[2] - width * right1[2];
5257 vert[ 6] = org2[0] - width * right2[0];
5258 vert[ 7] = org2[1] - width * right2[1];
5259 vert[ 8] = org2[2] - width * right2[2];
5260 vert[ 9] = org2[0] + width * right2[0];
5261 vert[10] = org2[1] + width * right2[1];
5262 vert[11] = org2[2] + width * right2[2];
5265 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5267 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)
5269 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
5273 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5274 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5276 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
5277 fog = RSurf_FogVertex(origin);
5279 R_Mesh_Matrix(&identitymatrix);
5280 GL_BlendFunc(blendfunc1, blendfunc2);
5282 GL_CullFace(GL_NONE);
5284 GL_DepthMask(false);
5285 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5286 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5287 GL_DepthTest(!depthdisable);
5289 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5290 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5291 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5292 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5293 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5294 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5295 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5296 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5297 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5298 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5299 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5300 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5302 R_Mesh_VertexPointer(vertex3f, 0, 0);
5303 R_Mesh_ColorPointer(NULL, 0, 0);
5304 R_Mesh_ResetTextureState();
5305 R_SetupGenericShader(true);
5306 R_Mesh_TexBind(0, R_GetTexture(texture));
5307 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5308 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5309 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5310 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5312 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5314 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5315 GL_BlendFunc(blendfunc1, GL_ONE);
5317 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5318 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5322 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5327 VectorSet(v, x, y, z);
5328 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5329 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5331 if (i == mesh->numvertices)
5333 if (mesh->numvertices < mesh->maxvertices)
5335 VectorCopy(v, vertex3f);
5336 mesh->numvertices++;
5338 return mesh->numvertices;
5344 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5348 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5349 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5350 e = mesh->element3i + mesh->numtriangles * 3;
5351 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5353 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5354 if (mesh->numtriangles < mesh->maxtriangles)
5359 mesh->numtriangles++;
5361 element[1] = element[2];
5365 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5369 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5370 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5371 e = mesh->element3i + mesh->numtriangles * 3;
5372 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5374 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5375 if (mesh->numtriangles < mesh->maxtriangles)
5380 mesh->numtriangles++;
5382 element[1] = element[2];
5386 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5387 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5389 int planenum, planenum2;
5392 mplane_t *plane, *plane2;
5394 double temppoints[2][256*3];
5395 // figure out how large a bounding box we need to properly compute this brush
5397 for (w = 0;w < numplanes;w++)
5398 maxdist = max(maxdist, fabs(planes[w].dist));
5399 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5400 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5401 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5405 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5406 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5408 if (planenum2 == planenum)
5410 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);
5413 if (tempnumpoints < 3)
5415 // generate elements forming a triangle fan for this polygon
5416 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5420 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)
5422 texturelayer_t *layer;
5423 layer = t->currentlayers + t->currentnumlayers++;
5425 layer->depthmask = depthmask;
5426 layer->blendfunc1 = blendfunc1;
5427 layer->blendfunc2 = blendfunc2;
5428 layer->texture = texture;
5429 layer->texmatrix = *matrix;
5430 layer->color[0] = r * r_refdef.view.colorscale;
5431 layer->color[1] = g * r_refdef.view.colorscale;
5432 layer->color[2] = b * r_refdef.view.colorscale;
5433 layer->color[3] = a;
5436 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5439 index = parms[2] + r_refdef.scene.time * parms[3];
5440 index -= floor(index);
5444 case Q3WAVEFUNC_NONE:
5445 case Q3WAVEFUNC_NOISE:
5446 case Q3WAVEFUNC_COUNT:
5449 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5450 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5451 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5452 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5453 case Q3WAVEFUNC_TRIANGLE:
5455 f = index - floor(index);
5466 return (float)(parms[0] + parms[1] * f);
5469 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5474 matrix4x4_t matrix, temp;
5475 switch(tcmod->tcmod)
5479 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5480 matrix = r_waterscrollmatrix;
5482 matrix = identitymatrix;
5484 case Q3TCMOD_ENTITYTRANSLATE:
5485 // this is used in Q3 to allow the gamecode to control texcoord
5486 // scrolling on the entity, which is not supported in darkplaces yet.
5487 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5489 case Q3TCMOD_ROTATE:
5490 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5491 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5492 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5495 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5497 case Q3TCMOD_SCROLL:
5498 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5500 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5501 w = (int) tcmod->parms[0];
5502 h = (int) tcmod->parms[1];
5503 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5505 idx = (int) floor(f * w * h);
5506 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5508 case Q3TCMOD_STRETCH:
5509 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5510 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5512 case Q3TCMOD_TRANSFORM:
5513 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5514 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5515 VectorSet(tcmat + 6, 0 , 0 , 1);
5516 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5517 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5519 case Q3TCMOD_TURBULENT:
5520 // this is handled in the RSurf_PrepareVertices function
5521 matrix = identitymatrix;
5525 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5528 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5530 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5531 char name[MAX_QPATH];
5532 skinframe_t *skinframe;
5533 unsigned char pixels[296*194];
5534 strlcpy(cache->name, skinname, sizeof(cache->name));
5535 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5536 if (developer_loading.integer)
5537 Con_Printf("loading %s\n", name);
5538 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5539 if (!skinframe || !skinframe->base)
5542 fs_offset_t filesize;
5544 f = FS_LoadFile(name, tempmempool, true, &filesize);
5547 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5548 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5552 cache->skinframe = skinframe;
5555 texture_t *R_GetCurrentTexture(texture_t *t)
5558 const entity_render_t *ent = rsurface.entity;
5559 dp_model_t *model = ent->model;
5560 q3shaderinfo_layer_tcmod_t *tcmod;
5562 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5563 return t->currentframe;
5564 t->update_lastrenderframe = r_frame;
5565 t->update_lastrenderentity = (void *)ent;
5567 // switch to an alternate material if this is a q1bsp animated material
5569 texture_t *texture = t;
5570 int s = ent->skinnum;
5571 if ((unsigned int)s >= (unsigned int)model->numskins)
5573 if (model->skinscenes)
5575 if (model->skinscenes[s].framecount > 1)
5576 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5578 s = model->skinscenes[s].firstframe;
5581 t = t + s * model->num_surfaces;
5584 // use an alternate animation if the entity's frame is not 0,
5585 // and only if the texture has an alternate animation
5586 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
5587 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5589 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5591 texture->currentframe = t;
5594 // update currentskinframe to be a qw skin or animation frame
5595 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[i].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl"))
5597 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5599 r_qwskincache_size = cl.maxclients;
5601 Mem_Free(r_qwskincache);
5602 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5604 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5605 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5606 t->currentskinframe = r_qwskincache[i].skinframe;
5607 if (t->currentskinframe == NULL)
5608 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5610 else if (t->numskinframes >= 2)
5611 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5612 if (t->backgroundnumskinframes >= 2)
5613 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
5615 t->currentmaterialflags = t->basematerialflags;
5616 t->currentalpha = ent->alpha;
5617 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5618 t->currentalpha *= r_wateralpha.value;
5619 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5620 t->currentalpha *= t->r_water_wateralpha;
5621 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5622 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5623 if (!(ent->flags & RENDER_LIGHT))
5624 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5625 else if (rsurface.modeltexcoordlightmap2f == NULL)
5627 // pick a model lighting mode
5628 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5629 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5631 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5633 if (ent->effects & EF_ADDITIVE)
5634 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5635 else if (t->currentalpha < 1)
5636 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5637 if (ent->effects & EF_DOUBLESIDED)
5638 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5639 if (ent->effects & EF_NODEPTHTEST)
5640 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5641 if (ent->flags & RENDER_VIEWMODEL)
5642 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5643 if (t->backgroundnumskinframes)
5644 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5645 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5647 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5648 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5651 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5653 // there is no tcmod
5654 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5656 t->currenttexmatrix = r_waterscrollmatrix;
5657 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5661 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5662 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5665 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5666 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5667 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5668 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5670 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5671 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5672 t->glosstexture = r_texture_black;
5673 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5674 t->backgroundglosstexture = r_texture_black;
5675 t->specularpower = r_shadow_glossexponent.value;
5676 // TODO: store reference values for these in the texture?
5677 t->specularscale = 0;
5678 if (r_shadow_gloss.integer > 0)
5680 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5682 if (r_shadow_glossintensity.value > 0)
5684 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5685 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5686 t->specularscale = r_shadow_glossintensity.value;
5689 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5691 t->glosstexture = r_texture_white;
5692 t->backgroundglosstexture = r_texture_white;
5693 t->specularscale = r_shadow_gloss2intensity.value;
5694 t->specularpower = r_shadow_gloss2exponent.value;
5697 t->specularscale *= t->specularscalemod;
5698 t->specularpower *= t->specularpowermod;
5700 // lightmaps mode looks bad with dlights using actual texturing, so turn
5701 // off the colormap and glossmap, but leave the normalmap on as it still
5702 // accurately represents the shading involved
5703 if (gl_lightmaps.integer)
5705 t->basetexture = r_texture_grey128;
5706 t->backgroundbasetexture = NULL;
5707 t->specularscale = 0;
5708 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5711 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5712 VectorClear(t->dlightcolor);
5713 t->currentnumlayers = 0;
5714 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5717 int blendfunc1, blendfunc2;
5719 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5721 blendfunc1 = GL_SRC_ALPHA;
5722 blendfunc2 = GL_ONE;
5724 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5726 blendfunc1 = GL_SRC_ALPHA;
5727 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5729 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5731 blendfunc1 = t->customblendfunc[0];
5732 blendfunc2 = t->customblendfunc[1];
5736 blendfunc1 = GL_ONE;
5737 blendfunc2 = GL_ZERO;
5739 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5740 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5741 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5742 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5744 // fullbright is not affected by r_refdef.lightmapintensity
5745 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]);
5746 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5747 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5748 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5749 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5753 vec3_t ambientcolor;
5755 // set the color tint used for lights affecting this surface
5756 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5758 // q3bsp has no lightmap updates, so the lightstylevalue that
5759 // would normally be baked into the lightmap must be
5760 // applied to the color
5761 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5762 if (ent->model->type == mod_brushq3)
5763 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5764 colorscale *= r_refdef.lightmapintensity;
5765 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5766 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5767 // basic lit geometry
5768 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]);
5769 // add pants/shirt if needed
5770 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5771 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5772 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5773 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5774 // now add ambient passes if needed
5775 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5777 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]);
5778 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5779 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
5780 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5781 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
5784 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5785 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]);
5786 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5788 // if this is opaque use alpha blend which will darken the earlier
5791 // if this is an alpha blended material, all the earlier passes
5792 // were darkened by fog already, so we only need to add the fog
5793 // color ontop through the fog mask texture
5795 // if this is an additive blended material, all the earlier passes
5796 // were darkened by fog already, and we should not add fog color
5797 // (because the background was not darkened, there is no fog color
5798 // that was lost behind it).
5799 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]);
5803 return t->currentframe;
5806 rsurfacestate_t rsurface;
5808 void R_Mesh_ResizeArrays(int newvertices)
5811 if (rsurface.array_size >= newvertices)
5813 if (rsurface.array_modelvertex3f)
5814 Mem_Free(rsurface.array_modelvertex3f);
5815 rsurface.array_size = (newvertices + 1023) & ~1023;
5816 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5817 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5818 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5819 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5820 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5821 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5822 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5823 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5824 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5825 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5826 rsurface.array_color4f = base + rsurface.array_size * 27;
5827 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5830 void RSurf_ActiveWorldEntity(void)
5832 dp_model_t *model = r_refdef.scene.worldmodel;
5833 //if (rsurface.entity == r_refdef.scene.worldentity)
5835 rsurface.entity = r_refdef.scene.worldentity;
5836 if (rsurface.array_size < model->surfmesh.num_vertices)
5837 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5838 rsurface.matrix = identitymatrix;
5839 rsurface.inversematrix = identitymatrix;
5840 R_Mesh_Matrix(&identitymatrix);
5841 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5842 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5843 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5844 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5845 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5846 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5847 VectorSet(rsurface.glowmod, 1, 1, 1);
5848 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5849 rsurface.frameblend[0].lerp = 1;
5850 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5851 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5852 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5853 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5854 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5855 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5856 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5857 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5858 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5859 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5860 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5861 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5862 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5863 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5864 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5865 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5866 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5867 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5868 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5869 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5870 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5871 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5872 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5873 rsurface.modelelement3i = model->surfmesh.data_element3i;
5874 rsurface.modelelement3s = model->surfmesh.data_element3s;
5875 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5876 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5877 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5878 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5879 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5880 rsurface.modelsurfaces = model->data_surfaces;
5881 rsurface.generatedvertex = false;
5882 rsurface.vertex3f = rsurface.modelvertex3f;
5883 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5884 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5885 rsurface.svector3f = rsurface.modelsvector3f;
5886 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5887 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5888 rsurface.tvector3f = rsurface.modeltvector3f;
5889 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5890 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5891 rsurface.normal3f = rsurface.modelnormal3f;
5892 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5893 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5894 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5897 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5899 dp_model_t *model = ent->model;
5900 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5902 rsurface.entity = (entity_render_t *)ent;
5903 if (rsurface.array_size < model->surfmesh.num_vertices)
5904 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5905 rsurface.matrix = ent->matrix;
5906 rsurface.inversematrix = ent->inversematrix;
5907 R_Mesh_Matrix(&rsurface.matrix);
5908 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
5909 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5910 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5911 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5912 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5913 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5914 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5915 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5916 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5917 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5918 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5919 VectorCopy(ent->glowmod, rsurface.glowmod);
5920 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5921 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5922 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5923 if (ent->model->brush.submodel)
5925 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5926 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5928 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5930 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5932 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5933 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5934 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5935 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5937 else if (wanttangents)
5939 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5940 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5941 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5942 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5943 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5945 else if (wantnormals)
5947 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5948 rsurface.modelsvector3f = NULL;
5949 rsurface.modeltvector3f = NULL;
5950 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5951 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5955 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5956 rsurface.modelsvector3f = NULL;
5957 rsurface.modeltvector3f = NULL;
5958 rsurface.modelnormal3f = NULL;
5959 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5961 rsurface.modelvertex3f_bufferobject = 0;
5962 rsurface.modelvertex3f_bufferoffset = 0;
5963 rsurface.modelsvector3f_bufferobject = 0;
5964 rsurface.modelsvector3f_bufferoffset = 0;
5965 rsurface.modeltvector3f_bufferobject = 0;
5966 rsurface.modeltvector3f_bufferoffset = 0;
5967 rsurface.modelnormal3f_bufferobject = 0;
5968 rsurface.modelnormal3f_bufferoffset = 0;
5969 rsurface.generatedvertex = true;
5973 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5974 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5975 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5976 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5977 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5978 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5979 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5980 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5981 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5982 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5983 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5984 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5985 rsurface.generatedvertex = false;
5987 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5988 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5989 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5990 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5991 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5992 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5993 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5994 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5995 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5996 rsurface.modelelement3i = model->surfmesh.data_element3i;
5997 rsurface.modelelement3s = model->surfmesh.data_element3s;
5998 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5999 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6000 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6001 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6002 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6003 rsurface.modelsurfaces = model->data_surfaces;
6004 rsurface.vertex3f = rsurface.modelvertex3f;
6005 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6006 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6007 rsurface.svector3f = rsurface.modelsvector3f;
6008 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6009 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6010 rsurface.tvector3f = rsurface.modeltvector3f;
6011 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6012 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6013 rsurface.normal3f = rsurface.modelnormal3f;
6014 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6015 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6016 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6019 float RSurf_FogVertex(const float *v)
6021 float len = VectorDistance(rsurface.localvieworigin, v);
6022 unsigned int fogmasktableindex;
6023 fogmasktableindex = (unsigned int)(len * r_refdef.fogmasktabledistmultiplier);
6024 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6027 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6028 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
6031 int texturesurfaceindex;
6036 const float *v1, *in_tc;
6038 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6040 q3shaderinfo_deform_t *deform;
6041 // 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
6042 if (rsurface.generatedvertex)
6044 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6045 generatenormals = true;
6046 for (i = 0;i < Q3MAXDEFORMS;i++)
6048 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6050 generatetangents = true;
6051 generatenormals = true;
6053 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6054 generatenormals = true;
6056 if (generatenormals && !rsurface.modelnormal3f)
6058 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6059 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6060 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6061 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6063 if (generatetangents && !rsurface.modelsvector3f)
6065 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6066 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6067 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6068 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6069 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6070 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6071 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);
6074 rsurface.vertex3f = rsurface.modelvertex3f;
6075 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6076 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6077 rsurface.svector3f = rsurface.modelsvector3f;
6078 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6079 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6080 rsurface.tvector3f = rsurface.modeltvector3f;
6081 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6082 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6083 rsurface.normal3f = rsurface.modelnormal3f;
6084 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6085 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6086 // if vertices are deformed (sprite flares and things in maps, possibly
6087 // water waves, bulges and other deformations), generate them into
6088 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6089 // (may be static model data or generated data for an animated model, or
6090 // the previous deform pass)
6091 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6093 switch (deform->deform)
6096 case Q3DEFORM_PROJECTIONSHADOW:
6097 case Q3DEFORM_TEXT0:
6098 case Q3DEFORM_TEXT1:
6099 case Q3DEFORM_TEXT2:
6100 case Q3DEFORM_TEXT3:
6101 case Q3DEFORM_TEXT4:
6102 case Q3DEFORM_TEXT5:
6103 case Q3DEFORM_TEXT6:
6104 case Q3DEFORM_TEXT7:
6107 case Q3DEFORM_AUTOSPRITE:
6108 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6109 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6110 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6111 VectorNormalize(newforward);
6112 VectorNormalize(newright);
6113 VectorNormalize(newup);
6114 // make deformed versions of only the model vertices used by the specified surfaces
6115 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6117 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6118 // a single autosprite surface can contain multiple sprites...
6119 for (j = 0;j < surface->num_vertices - 3;j += 4)
6121 VectorClear(center);
6122 for (i = 0;i < 4;i++)
6123 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6124 VectorScale(center, 0.25f, center);
6125 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6126 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6127 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6128 for (i = 0;i < 4;i++)
6130 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6131 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6134 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);
6135 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);
6137 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6138 rsurface.vertex3f_bufferobject = 0;
6139 rsurface.vertex3f_bufferoffset = 0;
6140 rsurface.svector3f = rsurface.array_deformedsvector3f;
6141 rsurface.svector3f_bufferobject = 0;
6142 rsurface.svector3f_bufferoffset = 0;
6143 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6144 rsurface.tvector3f_bufferobject = 0;
6145 rsurface.tvector3f_bufferoffset = 0;
6146 rsurface.normal3f = rsurface.array_deformednormal3f;
6147 rsurface.normal3f_bufferobject = 0;
6148 rsurface.normal3f_bufferoffset = 0;
6150 case Q3DEFORM_AUTOSPRITE2:
6151 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6152 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6153 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6154 VectorNormalize(newforward);
6155 VectorNormalize(newright);
6156 VectorNormalize(newup);
6157 // make deformed versions of only the model vertices used by the specified surfaces
6158 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6160 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6161 const float *v1, *v2;
6171 memset(shortest, 0, sizeof(shortest));
6172 // a single autosprite surface can contain multiple sprites...
6173 for (j = 0;j < surface->num_vertices - 3;j += 4)
6175 VectorClear(center);
6176 for (i = 0;i < 4;i++)
6177 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6178 VectorScale(center, 0.25f, center);
6179 // find the two shortest edges, then use them to define the
6180 // axis vectors for rotating around the central axis
6181 for (i = 0;i < 6;i++)
6183 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6184 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6186 Debug_PolygonBegin(NULL, 0);
6187 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6188 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);
6189 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6192 l = VectorDistance2(v1, v2);
6193 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6195 l += (1.0f / 1024.0f);
6196 if (shortest[0].length2 > l || i == 0)
6198 shortest[1] = shortest[0];
6199 shortest[0].length2 = l;
6200 shortest[0].v1 = v1;
6201 shortest[0].v2 = v2;
6203 else if (shortest[1].length2 > l || i == 1)
6205 shortest[1].length2 = l;
6206 shortest[1].v1 = v1;
6207 shortest[1].v2 = v2;
6210 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6211 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6213 Debug_PolygonBegin(NULL, 0);
6214 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6215 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);
6216 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6219 // this calculates the right vector from the shortest edge
6220 // and the up vector from the edge midpoints
6221 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6222 VectorNormalize(right);
6223 VectorSubtract(end, start, up);
6224 VectorNormalize(up);
6225 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6226 VectorSubtract(rsurface.localvieworigin, center, forward);
6227 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6228 VectorNegate(forward, forward);
6229 VectorReflect(forward, 0, up, forward);
6230 VectorNormalize(forward);
6231 CrossProduct(up, forward, newright);
6232 VectorNormalize(newright);
6234 Debug_PolygonBegin(NULL, 0);
6235 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);
6236 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6237 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6241 Debug_PolygonBegin(NULL, 0);
6242 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6243 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6244 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6247 // rotate the quad around the up axis vector, this is made
6248 // especially easy by the fact we know the quad is flat,
6249 // so we only have to subtract the center position and
6250 // measure distance along the right vector, and then
6251 // multiply that by the newright vector and add back the
6253 // we also need to subtract the old position to undo the
6254 // displacement from the center, which we do with a
6255 // DotProduct, the subtraction/addition of center is also
6256 // optimized into DotProducts here
6257 l = DotProduct(right, center);
6258 for (i = 0;i < 4;i++)
6260 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6261 f = DotProduct(right, v1) - l;
6262 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6265 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);
6266 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);
6268 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6269 rsurface.vertex3f_bufferobject = 0;
6270 rsurface.vertex3f_bufferoffset = 0;
6271 rsurface.svector3f = rsurface.array_deformedsvector3f;
6272 rsurface.svector3f_bufferobject = 0;
6273 rsurface.svector3f_bufferoffset = 0;
6274 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6275 rsurface.tvector3f_bufferobject = 0;
6276 rsurface.tvector3f_bufferoffset = 0;
6277 rsurface.normal3f = rsurface.array_deformednormal3f;
6278 rsurface.normal3f_bufferobject = 0;
6279 rsurface.normal3f_bufferoffset = 0;
6281 case Q3DEFORM_NORMAL:
6282 // deform the normals to make reflections wavey
6283 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6285 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6286 for (j = 0;j < surface->num_vertices;j++)
6289 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6290 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6291 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6292 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6293 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6294 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6295 VectorNormalize(normal);
6297 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);
6299 rsurface.svector3f = rsurface.array_deformedsvector3f;
6300 rsurface.svector3f_bufferobject = 0;
6301 rsurface.svector3f_bufferoffset = 0;
6302 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6303 rsurface.tvector3f_bufferobject = 0;
6304 rsurface.tvector3f_bufferoffset = 0;
6305 rsurface.normal3f = rsurface.array_deformednormal3f;
6306 rsurface.normal3f_bufferobject = 0;
6307 rsurface.normal3f_bufferoffset = 0;
6310 // deform vertex array to make wavey water and flags and such
6311 waveparms[0] = deform->waveparms[0];
6312 waveparms[1] = deform->waveparms[1];
6313 waveparms[2] = deform->waveparms[2];
6314 waveparms[3] = deform->waveparms[3];
6315 // this is how a divisor of vertex influence on deformation
6316 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6317 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6318 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6320 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6321 for (j = 0;j < surface->num_vertices;j++)
6323 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6324 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6325 // if the wavefunc depends on time, evaluate it per-vertex
6328 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6329 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6331 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6334 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6335 rsurface.vertex3f_bufferobject = 0;
6336 rsurface.vertex3f_bufferoffset = 0;
6338 case Q3DEFORM_BULGE:
6339 // deform vertex array to make the surface have moving bulges
6340 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6342 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6343 for (j = 0;j < surface->num_vertices;j++)
6345 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6346 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6349 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6350 rsurface.vertex3f_bufferobject = 0;
6351 rsurface.vertex3f_bufferoffset = 0;
6354 // deform vertex array
6355 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6356 VectorScale(deform->parms, scale, waveparms);
6357 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6359 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6360 for (j = 0;j < surface->num_vertices;j++)
6361 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6363 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6364 rsurface.vertex3f_bufferobject = 0;
6365 rsurface.vertex3f_bufferoffset = 0;
6369 // generate texcoords based on the chosen texcoord source
6370 switch(rsurface.texture->tcgen.tcgen)
6373 case Q3TCGEN_TEXTURE:
6374 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6375 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6376 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6378 case Q3TCGEN_LIGHTMAP:
6379 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6380 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6381 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6383 case Q3TCGEN_VECTOR:
6384 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6386 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6387 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)
6389 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6390 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6393 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6394 rsurface.texcoordtexture2f_bufferobject = 0;
6395 rsurface.texcoordtexture2f_bufferoffset = 0;
6397 case Q3TCGEN_ENVIRONMENT:
6398 // make environment reflections using a spheremap
6399 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6401 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6402 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6403 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6404 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6405 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6407 // identical to Q3A's method, but executed in worldspace so
6408 // carried models can be shiny too
6410 float viewer[3], d, reflected[3], worldreflected[3];
6412 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6413 // VectorNormalize(viewer);
6415 d = DotProduct(normal, viewer);
6417 reflected[0] = normal[0]*2*d - viewer[0];
6418 reflected[1] = normal[1]*2*d - viewer[1];
6419 reflected[2] = normal[2]*2*d - viewer[2];
6420 // note: this is proportinal to viewer, so we can normalize later
6422 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6423 VectorNormalize(worldreflected);
6425 // note: this sphere map only uses world x and z!
6426 // so positive and negative y will LOOK THE SAME.
6427 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6428 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6431 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6432 rsurface.texcoordtexture2f_bufferobject = 0;
6433 rsurface.texcoordtexture2f_bufferoffset = 0;
6436 // the only tcmod that needs software vertex processing is turbulent, so
6437 // check for it here and apply the changes if needed
6438 // and we only support that as the first one
6439 // (handling a mixture of turbulent and other tcmods would be problematic
6440 // without punting it entirely to a software path)
6441 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6443 amplitude = rsurface.texture->tcmods[0].parms[1];
6444 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6445 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6447 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6448 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)
6450 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6451 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6454 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6455 rsurface.texcoordtexture2f_bufferobject = 0;
6456 rsurface.texcoordtexture2f_bufferoffset = 0;
6458 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6459 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6460 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6461 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6464 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6467 const msurface_t *surface = texturesurfacelist[0];
6468 const msurface_t *surface2;
6473 // TODO: lock all array ranges before render, rather than on each surface
6474 if (texturenumsurfaces == 1)
6476 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6477 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);
6479 else if (r_batchmode.integer == 2)
6481 #define MAXBATCHTRIANGLES 4096
6482 int batchtriangles = 0;
6483 int batchelements[MAXBATCHTRIANGLES*3];
6484 for (i = 0;i < texturenumsurfaces;i = j)
6486 surface = texturesurfacelist[i];
6488 if (surface->num_triangles > MAXBATCHTRIANGLES)
6490 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);
6493 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6494 batchtriangles = surface->num_triangles;
6495 firstvertex = surface->num_firstvertex;
6496 endvertex = surface->num_firstvertex + surface->num_vertices;
6497 for (;j < texturenumsurfaces;j++)
6499 surface2 = texturesurfacelist[j];
6500 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6502 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6503 batchtriangles += surface2->num_triangles;
6504 firstvertex = min(firstvertex, surface2->num_firstvertex);
6505 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6507 surface2 = texturesurfacelist[j-1];
6508 numvertices = endvertex - firstvertex;
6509 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6512 else if (r_batchmode.integer == 1)
6514 for (i = 0;i < texturenumsurfaces;i = j)
6516 surface = texturesurfacelist[i];
6517 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6518 if (texturesurfacelist[j] != surface2)
6520 surface2 = texturesurfacelist[j-1];
6521 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6522 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6523 GL_LockArrays(surface->num_firstvertex, numvertices);
6524 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6529 for (i = 0;i < texturenumsurfaces;i++)
6531 surface = texturesurfacelist[i];
6532 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6533 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);
6538 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6540 int i, planeindex, vertexindex;
6544 r_waterstate_waterplane_t *p, *bestp;
6545 msurface_t *surface;
6546 if (r_waterstate.renderingscene)
6548 for (i = 0;i < texturenumsurfaces;i++)
6550 surface = texturesurfacelist[i];
6551 if (lightmaptexunit >= 0)
6552 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6553 if (deluxemaptexunit >= 0)
6554 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6555 // pick the closest matching water plane
6558 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6561 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6563 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6564 d += fabs(PlaneDiff(vert, &p->plane));
6566 if (bestd > d || !bestp)
6574 if (refractiontexunit >= 0)
6575 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6576 if (reflectiontexunit >= 0)
6577 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6581 if (refractiontexunit >= 0)
6582 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6583 if (reflectiontexunit >= 0)
6584 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6586 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6587 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);
6591 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6595 const msurface_t *surface = texturesurfacelist[0];
6596 const msurface_t *surface2;
6601 // TODO: lock all array ranges before render, rather than on each surface
6602 if (texturenumsurfaces == 1)
6604 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6605 if (deluxemaptexunit >= 0)
6606 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6607 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6608 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);
6610 else if (r_batchmode.integer == 2)
6612 #define MAXBATCHTRIANGLES 4096
6613 int batchtriangles = 0;
6614 int batchelements[MAXBATCHTRIANGLES*3];
6615 for (i = 0;i < texturenumsurfaces;i = j)
6617 surface = texturesurfacelist[i];
6618 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6619 if (deluxemaptexunit >= 0)
6620 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6622 if (surface->num_triangles > MAXBATCHTRIANGLES)
6624 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);
6627 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6628 batchtriangles = surface->num_triangles;
6629 firstvertex = surface->num_firstvertex;
6630 endvertex = surface->num_firstvertex + surface->num_vertices;
6631 for (;j < texturenumsurfaces;j++)
6633 surface2 = texturesurfacelist[j];
6634 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6636 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6637 batchtriangles += surface2->num_triangles;
6638 firstvertex = min(firstvertex, surface2->num_firstvertex);
6639 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6641 surface2 = texturesurfacelist[j-1];
6642 numvertices = endvertex - firstvertex;
6643 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6646 else if (r_batchmode.integer == 1)
6649 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6650 for (i = 0;i < texturenumsurfaces;i = j)
6652 surface = texturesurfacelist[i];
6653 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6654 if (texturesurfacelist[j] != surface2)
6656 Con_Printf(" %i", j - i);
6659 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6661 for (i = 0;i < texturenumsurfaces;i = j)
6663 surface = texturesurfacelist[i];
6664 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6665 if (deluxemaptexunit >= 0)
6666 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6667 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6668 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6671 Con_Printf(" %i", j - i);
6673 surface2 = texturesurfacelist[j-1];
6674 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6675 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6676 GL_LockArrays(surface->num_firstvertex, numvertices);
6677 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6685 for (i = 0;i < texturenumsurfaces;i++)
6687 surface = texturesurfacelist[i];
6688 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6689 if (deluxemaptexunit >= 0)
6690 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6691 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6692 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);
6697 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6700 int texturesurfaceindex;
6701 if (r_showsurfaces.integer == 2)
6703 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6705 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6706 for (j = 0;j < surface->num_triangles;j++)
6708 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6709 GL_Color(f, f, f, 1);
6710 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6716 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6718 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6719 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6720 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);
6721 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6722 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);
6727 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6729 int texturesurfaceindex;
6732 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6734 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6735 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)
6743 rsurface.lightmapcolor4f = rsurface.array_color4f;
6744 rsurface.lightmapcolor4f_bufferobject = 0;
6745 rsurface.lightmapcolor4f_bufferoffset = 0;
6748 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6750 int texturesurfaceindex;
6754 if (rsurface.lightmapcolor4f)
6756 // generate color arrays for the surfaces in this list
6757 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6759 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6760 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)
6762 f = RSurf_FogVertex(v);
6772 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6774 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6775 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)
6777 f = RSurf_FogVertex(v);
6785 rsurface.lightmapcolor4f = rsurface.array_color4f;
6786 rsurface.lightmapcolor4f_bufferobject = 0;
6787 rsurface.lightmapcolor4f_bufferoffset = 0;
6790 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6792 int texturesurfaceindex;
6796 if (!rsurface.lightmapcolor4f)
6798 // generate color arrays for the surfaces in this list
6799 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6801 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6802 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)
6804 f = RSurf_FogVertex(v);
6805 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6806 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6807 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6811 rsurface.lightmapcolor4f = rsurface.array_color4f;
6812 rsurface.lightmapcolor4f_bufferobject = 0;
6813 rsurface.lightmapcolor4f_bufferoffset = 0;
6816 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6818 int texturesurfaceindex;
6821 if (!rsurface.lightmapcolor4f)
6823 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6825 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6826 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)
6834 rsurface.lightmapcolor4f = rsurface.array_color4f;
6835 rsurface.lightmapcolor4f_bufferobject = 0;
6836 rsurface.lightmapcolor4f_bufferoffset = 0;
6839 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
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)
6851 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6852 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6853 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6857 rsurface.lightmapcolor4f = rsurface.array_color4f;
6858 rsurface.lightmapcolor4f_bufferobject = 0;
6859 rsurface.lightmapcolor4f_bufferoffset = 0;
6862 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6865 rsurface.lightmapcolor4f = NULL;
6866 rsurface.lightmapcolor4f_bufferobject = 0;
6867 rsurface.lightmapcolor4f_bufferoffset = 0;
6868 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6869 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6870 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6871 GL_Color(r, g, b, a);
6872 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6875 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6877 // TODO: optimize applyfog && applycolor case
6878 // just apply fog if necessary, and tint the fog color array if necessary
6879 rsurface.lightmapcolor4f = NULL;
6880 rsurface.lightmapcolor4f_bufferobject = 0;
6881 rsurface.lightmapcolor4f_bufferoffset = 0;
6882 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6883 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6884 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6885 GL_Color(r, g, b, a);
6886 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6889 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6891 int texturesurfaceindex;
6895 if (texturesurfacelist[0]->lightmapinfo)
6897 // generate color arrays for the surfaces in this list
6898 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6900 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6901 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6903 if (surface->lightmapinfo->samples)
6905 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6906 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6907 VectorScale(lm, scale, c);
6908 if (surface->lightmapinfo->styles[1] != 255)
6910 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6912 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6913 VectorMA(c, scale, lm, c);
6914 if (surface->lightmapinfo->styles[2] != 255)
6917 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6918 VectorMA(c, scale, lm, c);
6919 if (surface->lightmapinfo->styles[3] != 255)
6922 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6923 VectorMA(c, scale, lm, c);
6933 rsurface.lightmapcolor4f = rsurface.array_color4f;
6934 rsurface.lightmapcolor4f_bufferobject = 0;
6935 rsurface.lightmapcolor4f_bufferoffset = 0;
6939 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6940 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6941 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6943 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6944 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6945 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6946 GL_Color(r, g, b, a);
6947 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6950 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6952 int texturesurfaceindex;
6955 float *v, *c, *c2, alpha;
6956 vec3_t ambientcolor;
6957 vec3_t diffusecolor;
6961 VectorCopy(rsurface.modellight_lightdir, lightdir);
6962 f = 0.5f * r_refdef.lightmapintensity;
6963 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6964 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6965 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6966 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6967 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6968 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6970 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6972 // generate color arrays for the surfaces in this list
6973 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6975 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6976 int numverts = surface->num_vertices;
6977 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6978 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6979 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6980 // q3-style directional shading
6981 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6983 if ((f = DotProduct(c2, lightdir)) > 0)
6984 VectorMA(ambientcolor, f, diffusecolor, c);
6986 VectorCopy(ambientcolor, c);
6994 rsurface.lightmapcolor4f = rsurface.array_color4f;
6995 rsurface.lightmapcolor4f_bufferobject = 0;
6996 rsurface.lightmapcolor4f_bufferoffset = 0;
6997 *applycolor = false;
7001 *r = ambientcolor[0];
7002 *g = ambientcolor[1];
7003 *b = ambientcolor[2];
7004 rsurface.lightmapcolor4f = NULL;
7005 rsurface.lightmapcolor4f_bufferobject = 0;
7006 rsurface.lightmapcolor4f_bufferoffset = 0;
7010 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7012 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7013 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7014 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7015 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7016 GL_Color(r, g, b, a);
7017 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7020 void RSurf_SetupDepthAndCulling(void)
7022 // submodels are biased to avoid z-fighting with world surfaces that they
7023 // may be exactly overlapping (avoids z-fighting artifacts on certain
7024 // doors and things in Quake maps)
7025 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7026 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7027 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7028 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7031 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
7033 // transparent sky would be ridiculous
7034 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7036 R_SetupGenericShader(false);
7037 skyrenderlater = true;
7038 RSurf_SetupDepthAndCulling();
7040 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7041 // skymasking on them, and Quake3 never did sky masking (unlike
7042 // software Quake and software Quake2), so disable the sky masking
7043 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7044 // and skymasking also looks very bad when noclipping outside the
7045 // level, so don't use it then either.
7046 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7048 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7049 R_Mesh_ColorPointer(NULL, 0, 0);
7050 R_Mesh_ResetTextureState();
7051 if (skyrendermasked)
7053 R_SetupDepthOrShadowShader();
7054 // depth-only (masking)
7055 GL_ColorMask(0,0,0,0);
7056 // just to make sure that braindead drivers don't draw
7057 // anything despite that colormask...
7058 GL_BlendFunc(GL_ZERO, GL_ONE);
7062 R_SetupGenericShader(false);
7064 GL_BlendFunc(GL_ONE, GL_ZERO);
7066 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7067 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7068 if (skyrendermasked)
7069 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7071 R_Mesh_ResetTextureState();
7072 GL_Color(1, 1, 1, 1);
7075 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7077 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7080 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7081 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7082 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7083 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7084 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7085 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7086 if (rsurface.texture->backgroundcurrentskinframe)
7088 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7089 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7090 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7091 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7093 if(rsurface.texture->colormapping)
7095 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7096 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7098 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7099 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7100 R_Mesh_ColorPointer(NULL, 0, 0);
7102 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7104 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7106 // render background
7107 GL_BlendFunc(GL_ONE, GL_ZERO);
7109 GL_AlphaTest(false);
7111 GL_Color(1, 1, 1, 1);
7112 R_Mesh_ColorPointer(NULL, 0, 0);
7114 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7115 if (r_glsl_permutation)
7117 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7118 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7119 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7120 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7121 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7122 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7123 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);
7125 GL_LockArrays(0, 0);
7127 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7128 GL_DepthMask(false);
7129 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7130 R_Mesh_ColorPointer(NULL, 0, 0);
7132 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7133 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7134 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7137 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7138 if (!r_glsl_permutation)
7141 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7142 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7143 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7144 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7145 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7146 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7148 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7150 GL_BlendFunc(GL_ONE, GL_ZERO);
7152 GL_AlphaTest(false);
7156 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7157 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7158 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7161 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7163 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7164 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);
7166 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7170 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7171 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);
7173 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7175 GL_LockArrays(0, 0);
7178 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7180 // OpenGL 1.3 path - anything not completely ancient
7181 int texturesurfaceindex;
7182 qboolean applycolor;
7186 const texturelayer_t *layer;
7187 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7189 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7192 int layertexrgbscale;
7193 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7195 if (layerindex == 0)
7199 GL_AlphaTest(false);
7200 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7203 GL_DepthMask(layer->depthmask && writedepth);
7204 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7205 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7207 layertexrgbscale = 4;
7208 VectorScale(layer->color, 0.25f, layercolor);
7210 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7212 layertexrgbscale = 2;
7213 VectorScale(layer->color, 0.5f, layercolor);
7217 layertexrgbscale = 1;
7218 VectorScale(layer->color, 1.0f, layercolor);
7220 layercolor[3] = layer->color[3];
7221 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7222 R_Mesh_ColorPointer(NULL, 0, 0);
7223 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7224 switch (layer->type)
7226 case TEXTURELAYERTYPE_LITTEXTURE:
7227 memset(&m, 0, sizeof(m));
7228 m.tex[0] = R_GetTexture(r_texture_white);
7229 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7230 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7231 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7232 m.tex[1] = R_GetTexture(layer->texture);
7233 m.texmatrix[1] = layer->texmatrix;
7234 m.texrgbscale[1] = layertexrgbscale;
7235 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7236 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7237 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7238 R_Mesh_TextureState(&m);
7239 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7240 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7241 else if (rsurface.uselightmaptexture)
7242 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7244 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7246 case TEXTURELAYERTYPE_TEXTURE:
7247 memset(&m, 0, sizeof(m));
7248 m.tex[0] = R_GetTexture(layer->texture);
7249 m.texmatrix[0] = layer->texmatrix;
7250 m.texrgbscale[0] = layertexrgbscale;
7251 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7252 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7253 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7254 R_Mesh_TextureState(&m);
7255 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7257 case TEXTURELAYERTYPE_FOG:
7258 memset(&m, 0, sizeof(m));
7259 m.texrgbscale[0] = layertexrgbscale;
7262 m.tex[0] = R_GetTexture(layer->texture);
7263 m.texmatrix[0] = layer->texmatrix;
7264 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7265 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7266 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7268 R_Mesh_TextureState(&m);
7269 // generate a color array for the fog pass
7270 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7271 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7275 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7276 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)
7278 f = 1 - RSurf_FogVertex(v);
7279 c[0] = layercolor[0];
7280 c[1] = layercolor[1];
7281 c[2] = layercolor[2];
7282 c[3] = f * layercolor[3];
7285 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7288 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7290 GL_LockArrays(0, 0);
7293 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7295 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7296 GL_AlphaTest(false);
7300 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7302 // OpenGL 1.1 - crusty old voodoo path
7303 int texturesurfaceindex;
7307 const texturelayer_t *layer;
7308 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7310 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7312 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7314 if (layerindex == 0)
7318 GL_AlphaTest(false);
7319 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7322 GL_DepthMask(layer->depthmask && writedepth);
7323 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7324 R_Mesh_ColorPointer(NULL, 0, 0);
7325 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7326 switch (layer->type)
7328 case TEXTURELAYERTYPE_LITTEXTURE:
7329 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7331 // two-pass lit texture with 2x rgbscale
7332 // first the lightmap pass
7333 memset(&m, 0, sizeof(m));
7334 m.tex[0] = R_GetTexture(r_texture_white);
7335 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7336 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7337 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7338 R_Mesh_TextureState(&m);
7339 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7340 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7341 else if (rsurface.uselightmaptexture)
7342 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7344 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7345 GL_LockArrays(0, 0);
7346 // then apply the texture to it
7347 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7348 memset(&m, 0, sizeof(m));
7349 m.tex[0] = R_GetTexture(layer->texture);
7350 m.texmatrix[0] = layer->texmatrix;
7351 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7352 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7353 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7354 R_Mesh_TextureState(&m);
7355 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);
7359 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7360 memset(&m, 0, sizeof(m));
7361 m.tex[0] = R_GetTexture(layer->texture);
7362 m.texmatrix[0] = layer->texmatrix;
7363 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7364 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7365 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7366 R_Mesh_TextureState(&m);
7367 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7368 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);
7370 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);
7373 case TEXTURELAYERTYPE_TEXTURE:
7374 // singletexture unlit texture with transparency support
7375 memset(&m, 0, sizeof(m));
7376 m.tex[0] = R_GetTexture(layer->texture);
7377 m.texmatrix[0] = layer->texmatrix;
7378 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7379 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7380 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7381 R_Mesh_TextureState(&m);
7382 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);
7384 case TEXTURELAYERTYPE_FOG:
7385 // singletexture fogging
7386 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7389 memset(&m, 0, sizeof(m));
7390 m.tex[0] = R_GetTexture(layer->texture);
7391 m.texmatrix[0] = layer->texmatrix;
7392 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7393 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7394 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7395 R_Mesh_TextureState(&m);
7398 R_Mesh_ResetTextureState();
7399 // generate a color array for the fog pass
7400 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7404 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7405 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)
7407 f = 1 - RSurf_FogVertex(v);
7408 c[0] = layer->color[0];
7409 c[1] = layer->color[1];
7410 c[2] = layer->color[2];
7411 c[3] = f * layer->color[3];
7414 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7417 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7419 GL_LockArrays(0, 0);
7422 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7424 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7425 GL_AlphaTest(false);
7429 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7433 GL_AlphaTest(false);
7434 R_Mesh_ColorPointer(NULL, 0, 0);
7435 R_Mesh_ResetTextureState();
7436 R_SetupGenericShader(false);
7438 if(rsurface.texture && rsurface.texture->currentskinframe)
7440 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7441 c[3] *= rsurface.texture->currentalpha;
7451 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7453 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7454 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7455 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7458 // brighten it up (as texture value 127 means "unlit")
7459 c[0] *= 2 * r_refdef.view.colorscale;
7460 c[1] *= 2 * r_refdef.view.colorscale;
7461 c[2] *= 2 * r_refdef.view.colorscale;
7463 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7464 c[3] *= r_wateralpha.value;
7466 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7468 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7469 GL_DepthMask(false);
7471 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7473 GL_BlendFunc(GL_ONE, GL_ONE);
7474 GL_DepthMask(false);
7476 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7478 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7479 GL_DepthMask(false);
7481 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7483 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7484 GL_DepthMask(false);
7488 GL_BlendFunc(GL_ONE, GL_ZERO);
7489 GL_DepthMask(writedepth);
7492 rsurface.lightmapcolor4f = NULL;
7494 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7496 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7498 rsurface.lightmapcolor4f = NULL;
7499 rsurface.lightmapcolor4f_bufferobject = 0;
7500 rsurface.lightmapcolor4f_bufferoffset = 0;
7502 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7504 qboolean applycolor = true;
7507 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7509 r_refdef.lightmapintensity = 1;
7510 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7511 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7515 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7517 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7518 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7519 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7522 if(!rsurface.lightmapcolor4f)
7523 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7525 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7526 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7527 if(r_refdef.fogenabled)
7528 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7530 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7531 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7534 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7537 RSurf_SetupDepthAndCulling();
7538 if (r_showsurfaces.integer == 3)
7539 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7540 else if (r_glsl.integer && gl_support_fragment_shader)
7541 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7542 else if (gl_combine.integer && r_textureunits.integer >= 2)
7543 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7545 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7549 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7552 RSurf_SetupDepthAndCulling();
7553 if (r_showsurfaces.integer == 3)
7554 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7555 else if (r_glsl.integer && gl_support_fragment_shader)
7556 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7557 else if (gl_combine.integer && r_textureunits.integer >= 2)
7558 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7560 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7564 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7567 int texturenumsurfaces, endsurface;
7569 msurface_t *surface;
7570 msurface_t *texturesurfacelist[1024];
7572 // if the model is static it doesn't matter what value we give for
7573 // wantnormals and wanttangents, so this logic uses only rules applicable
7574 // to a model, knowing that they are meaningless otherwise
7575 if (ent == r_refdef.scene.worldentity)
7576 RSurf_ActiveWorldEntity();
7577 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7578 RSurf_ActiveModelEntity(ent, false, false);
7580 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7582 for (i = 0;i < numsurfaces;i = j)
7585 surface = rsurface.modelsurfaces + surfacelist[i];
7586 texture = surface->texture;
7587 rsurface.texture = R_GetCurrentTexture(texture);
7588 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7589 // scan ahead until we find a different texture
7590 endsurface = min(i + 1024, numsurfaces);
7591 texturenumsurfaces = 0;
7592 texturesurfacelist[texturenumsurfaces++] = surface;
7593 for (;j < endsurface;j++)
7595 surface = rsurface.modelsurfaces + surfacelist[j];
7596 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7598 texturesurfacelist[texturenumsurfaces++] = surface;
7600 // render the range of surfaces
7601 if (ent == r_refdef.scene.worldentity)
7602 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7604 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7606 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7607 GL_AlphaTest(false);
7610 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7612 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7616 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7618 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7620 RSurf_SetupDepthAndCulling();
7621 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7622 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7624 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7626 RSurf_SetupDepthAndCulling();
7627 GL_AlphaTest(false);
7628 R_Mesh_ColorPointer(NULL, 0, 0);
7629 R_Mesh_ResetTextureState();
7630 R_SetupGenericShader(false);
7631 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7633 GL_BlendFunc(GL_ONE, GL_ZERO);
7634 GL_Color(0, 0, 0, 1);
7635 GL_DepthTest(writedepth);
7636 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7638 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7640 RSurf_SetupDepthAndCulling();
7641 GL_AlphaTest(false);
7642 R_Mesh_ColorPointer(NULL, 0, 0);
7643 R_Mesh_ResetTextureState();
7644 R_SetupGenericShader(false);
7645 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7647 GL_BlendFunc(GL_ONE, GL_ZERO);
7649 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7651 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7652 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7653 else if (!rsurface.texture->currentnumlayers)
7655 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7657 // transparent surfaces get pushed off into the transparent queue
7658 int surfacelistindex;
7659 const msurface_t *surface;
7660 vec3_t tempcenter, center;
7661 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7663 surface = texturesurfacelist[surfacelistindex];
7664 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7665 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7666 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7667 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7668 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7673 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7674 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7679 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7683 // break the surface list down into batches by texture and use of lightmapping
7684 for (i = 0;i < numsurfaces;i = j)
7687 // texture is the base texture pointer, rsurface.texture is the
7688 // current frame/skin the texture is directing us to use (for example
7689 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7690 // use skin 1 instead)
7691 texture = surfacelist[i]->texture;
7692 rsurface.texture = R_GetCurrentTexture(texture);
7693 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7694 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7696 // if this texture is not the kind we want, skip ahead to the next one
7697 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7701 // simply scan ahead until we find a different texture or lightmap state
7702 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7704 // render the range of surfaces
7705 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7709 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7714 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7716 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7718 RSurf_SetupDepthAndCulling();
7719 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7720 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7722 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7724 RSurf_SetupDepthAndCulling();
7725 GL_AlphaTest(false);
7726 R_Mesh_ColorPointer(NULL, 0, 0);
7727 R_Mesh_ResetTextureState();
7728 R_SetupGenericShader(false);
7729 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7731 GL_BlendFunc(GL_ONE, GL_ZERO);
7732 GL_Color(0, 0, 0, 1);
7733 GL_DepthTest(writedepth);
7734 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7736 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7738 RSurf_SetupDepthAndCulling();
7739 GL_AlphaTest(false);
7740 R_Mesh_ColorPointer(NULL, 0, 0);
7741 R_Mesh_ResetTextureState();
7742 R_SetupGenericShader(false);
7743 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7745 GL_BlendFunc(GL_ONE, GL_ZERO);
7747 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7749 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7750 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7751 else if (!rsurface.texture->currentnumlayers)
7753 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7755 // transparent surfaces get pushed off into the transparent queue
7756 int surfacelistindex;
7757 const msurface_t *surface;
7758 vec3_t tempcenter, center;
7759 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7761 surface = texturesurfacelist[surfacelistindex];
7762 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7763 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7764 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7765 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7766 if (queueentity->transparent_offset) // transparent offset
7768 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
7769 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
7770 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
7772 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7777 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7778 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7783 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7787 // break the surface list down into batches by texture and use of lightmapping
7788 for (i = 0;i < numsurfaces;i = j)
7791 // texture is the base texture pointer, rsurface.texture is the
7792 // current frame/skin the texture is directing us to use (for example
7793 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7794 // use skin 1 instead)
7795 texture = surfacelist[i]->texture;
7796 rsurface.texture = R_GetCurrentTexture(texture);
7797 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7798 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7800 // if this texture is not the kind we want, skip ahead to the next one
7801 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7805 // simply scan ahead until we find a different texture or lightmap state
7806 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7808 // render the range of surfaces
7809 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7813 float locboxvertex3f[6*4*3] =
7815 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7816 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7817 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7818 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7819 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7820 1,0,0, 0,0,0, 0,1,0, 1,1,0
7823 unsigned short locboxelements[6*2*3] =
7833 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7836 cl_locnode_t *loc = (cl_locnode_t *)ent;
7838 float vertex3f[6*4*3];
7840 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7841 GL_DepthMask(false);
7842 GL_DepthRange(0, 1);
7843 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7845 GL_CullFace(GL_NONE);
7846 R_Mesh_Matrix(&identitymatrix);
7848 R_Mesh_VertexPointer(vertex3f, 0, 0);
7849 R_Mesh_ColorPointer(NULL, 0, 0);
7850 R_Mesh_ResetTextureState();
7851 R_SetupGenericShader(false);
7854 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7855 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7856 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7857 surfacelist[0] < 0 ? 0.5f : 0.125f);
7859 if (VectorCompare(loc->mins, loc->maxs))
7861 VectorSet(size, 2, 2, 2);
7862 VectorMA(loc->mins, -0.5f, size, mins);
7866 VectorCopy(loc->mins, mins);
7867 VectorSubtract(loc->maxs, loc->mins, size);
7870 for (i = 0;i < 6*4*3;)
7871 for (j = 0;j < 3;j++, i++)
7872 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7874 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7877 void R_DrawLocs(void)
7880 cl_locnode_t *loc, *nearestloc;
7882 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7883 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7885 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7886 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7890 void R_DrawDebugModel(entity_render_t *ent)
7892 int i, j, k, l, flagsmask;
7893 const int *elements;
7895 msurface_t *surface;
7896 dp_model_t *model = ent->model;
7899 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7901 R_Mesh_ColorPointer(NULL, 0, 0);
7902 R_Mesh_ResetTextureState();
7903 R_SetupGenericShader(false);
7904 GL_DepthRange(0, 1);
7905 GL_DepthTest(!r_showdisabledepthtest.integer);
7906 GL_DepthMask(false);
7907 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7909 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7911 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7912 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7914 if (brush->colbrushf && brush->colbrushf->numtriangles)
7916 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7917 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);
7918 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7921 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7923 if (surface->num_collisiontriangles)
7925 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7926 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);
7927 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7932 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7934 if (r_showtris.integer || r_shownormals.integer)
7936 if (r_showdisabledepthtest.integer)
7938 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7939 GL_DepthMask(false);
7943 GL_BlendFunc(GL_ONE, GL_ZERO);
7946 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7948 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7950 rsurface.texture = R_GetCurrentTexture(surface->texture);
7951 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7953 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7954 if (r_showtris.value > 0)
7956 if (!rsurface.texture->currentlayers->depthmask)
7957 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7958 else if (ent == r_refdef.scene.worldentity)
7959 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7961 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7962 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7963 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7964 R_Mesh_ColorPointer(NULL, 0, 0);
7965 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7966 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7967 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7968 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);
7969 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7972 if (r_shownormals.value < 0)
7975 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7977 VectorCopy(rsurface.vertex3f + l * 3, v);
7978 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7979 qglVertex3f(v[0], v[1], v[2]);
7980 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7981 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7982 qglVertex3f(v[0], v[1], v[2]);
7987 if (r_shownormals.value > 0)
7990 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7992 VectorCopy(rsurface.vertex3f + l * 3, v);
7993 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7994 qglVertex3f(v[0], v[1], v[2]);
7995 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7996 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7997 qglVertex3f(v[0], v[1], v[2]);
8002 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8004 VectorCopy(rsurface.vertex3f + l * 3, v);
8005 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8006 qglVertex3f(v[0], v[1], v[2]);
8007 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8008 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8009 qglVertex3f(v[0], v[1], v[2]);
8014 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8016 VectorCopy(rsurface.vertex3f + l * 3, v);
8017 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8018 qglVertex3f(v[0], v[1], v[2]);
8019 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8020 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8021 qglVertex3f(v[0], v[1], v[2]);
8028 rsurface.texture = NULL;
8032 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8033 int r_maxsurfacelist = 0;
8034 msurface_t **r_surfacelist = NULL;
8035 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8037 int i, j, endj, f, flagsmask;
8039 dp_model_t *model = r_refdef.scene.worldmodel;
8040 msurface_t *surfaces;
8041 unsigned char *update;
8042 int numsurfacelist = 0;
8046 if (r_maxsurfacelist < model->num_surfaces)
8048 r_maxsurfacelist = model->num_surfaces;
8050 Mem_Free(r_surfacelist);
8051 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8054 RSurf_ActiveWorldEntity();
8056 surfaces = model->data_surfaces;
8057 update = model->brushq1.lightmapupdateflags;
8059 // update light styles on this submodel
8060 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8062 model_brush_lightstyleinfo_t *style;
8063 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8065 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8067 int *list = style->surfacelist;
8068 style->value = r_refdef.scene.lightstylevalue[style->style];
8069 for (j = 0;j < style->numsurfaces;j++)
8070 update[list[j]] = true;
8075 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8079 R_DrawDebugModel(r_refdef.scene.worldentity);
8080 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8086 rsurface.uselightmaptexture = false;
8087 rsurface.texture = NULL;
8088 rsurface.rtlight = NULL;
8090 // add visible surfaces to draw list
8091 for (i = 0;i < model->nummodelsurfaces;i++)
8093 j = model->sortedmodelsurfaces[i];
8094 if (r_refdef.viewcache.world_surfacevisible[j])
8095 r_surfacelist[numsurfacelist++] = surfaces + j;
8097 // update lightmaps if needed
8099 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8100 if (r_refdef.viewcache.world_surfacevisible[j])
8102 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8103 // don't do anything if there were no surfaces
8104 if (!numsurfacelist)
8106 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8109 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8110 GL_AlphaTest(false);
8112 // add to stats if desired
8113 if (r_speeds.integer && !skysurfaces && !depthonly)
8115 r_refdef.stats.world_surfaces += numsurfacelist;
8116 for (j = 0;j < numsurfacelist;j++)
8117 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8119 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8122 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8124 int i, j, endj, f, flagsmask;
8126 dp_model_t *model = ent->model;
8127 msurface_t *surfaces;
8128 unsigned char *update;
8129 int numsurfacelist = 0;
8133 if (r_maxsurfacelist < model->num_surfaces)
8135 r_maxsurfacelist = model->num_surfaces;
8137 Mem_Free(r_surfacelist);
8138 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8141 // if the model is static it doesn't matter what value we give for
8142 // wantnormals and wanttangents, so this logic uses only rules applicable
8143 // to a model, knowing that they are meaningless otherwise
8144 if (ent == r_refdef.scene.worldentity)
8145 RSurf_ActiveWorldEntity();
8146 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8147 RSurf_ActiveModelEntity(ent, false, false);
8149 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8151 surfaces = model->data_surfaces;
8152 update = model->brushq1.lightmapupdateflags;
8154 // update light styles
8155 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8157 model_brush_lightstyleinfo_t *style;
8158 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8160 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8162 int *list = style->surfacelist;
8163 style->value = r_refdef.scene.lightstylevalue[style->style];
8164 for (j = 0;j < style->numsurfaces;j++)
8165 update[list[j]] = true;
8170 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8174 R_DrawDebugModel(ent);
8175 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8181 rsurface.uselightmaptexture = false;
8182 rsurface.texture = NULL;
8183 rsurface.rtlight = NULL;
8185 // add visible surfaces to draw list
8186 for (i = 0;i < model->nummodelsurfaces;i++)
8187 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8188 // don't do anything if there were no surfaces
8189 if (!numsurfacelist)
8191 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8194 // update lightmaps if needed
8196 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8198 R_BuildLightMap(ent, surfaces + j);
8199 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8200 GL_AlphaTest(false);
8202 // add to stats if desired
8203 if (r_speeds.integer && !skysurfaces && !depthonly)
8205 r_refdef.stats.entities_surfaces += numsurfacelist;
8206 for (j = 0;j < numsurfacelist;j++)
8207 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8209 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity