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");
4864 R_AnimCache_CacheVisibleEntities();
4866 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4868 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4869 if (r_timereport_active)
4870 R_TimeReport("worlddepth");
4872 if (r_depthfirst.integer >= 2)
4874 R_DrawModelsDepth();
4875 if (r_timereport_active)
4876 R_TimeReport("modeldepth");
4879 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4881 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4882 if (r_timereport_active)
4883 R_TimeReport("world");
4886 // don't let sound skip if going slow
4887 if (r_refdef.scene.extraupdate)
4891 if (r_timereport_active)
4892 R_TimeReport("models");
4894 // don't let sound skip if going slow
4895 if (r_refdef.scene.extraupdate)
4898 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4900 R_DrawModelShadows();
4901 R_ResetViewRendering3D();
4902 // don't let sound skip if going slow
4903 if (r_refdef.scene.extraupdate)
4907 R_ShadowVolumeLighting(false);
4908 if (r_timereport_active)
4909 R_TimeReport("rtlights");
4911 // don't let sound skip if going slow
4912 if (r_refdef.scene.extraupdate)
4915 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4917 R_DrawModelShadows();
4918 R_ResetViewRendering3D();
4919 // don't let sound skip if going slow
4920 if (r_refdef.scene.extraupdate)
4924 if (cl.csqc_vidvars.drawworld)
4926 R_DrawLightningBeams();
4927 if (r_timereport_active)
4928 R_TimeReport("lightning");
4931 if (r_timereport_active)
4932 R_TimeReport("decals");
4935 if (r_timereport_active)
4936 R_TimeReport("particles");
4939 if (r_timereport_active)
4940 R_TimeReport("explosions");
4943 R_SetupGenericShader(true);
4944 VM_CL_AddPolygonsToMeshQueue();
4946 if (r_refdef.view.showdebug)
4948 if (cl_locs_show.integer)
4951 if (r_timereport_active)
4952 R_TimeReport("showlocs");
4955 if (r_drawportals.integer)
4958 if (r_timereport_active)
4959 R_TimeReport("portals");
4962 if (r_showbboxes.value > 0)
4964 R_DrawEntityBBoxes();
4965 if (r_timereport_active)
4966 R_TimeReport("bboxes");
4970 R_SetupGenericShader(true);
4971 R_MeshQueue_RenderTransparent();
4972 if (r_timereport_active)
4973 R_TimeReport("drawtrans");
4975 R_SetupGenericShader(true);
4977 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))
4979 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4980 if (r_timereport_active)
4981 R_TimeReport("worlddebug");
4982 R_DrawModelsDebug();
4983 if (r_timereport_active)
4984 R_TimeReport("modeldebug");
4987 R_SetupGenericShader(true);
4989 if (cl.csqc_vidvars.drawworld)
4992 if (r_timereport_active)
4993 R_TimeReport("coronas");
4996 // don't let sound skip if going slow
4997 if (r_refdef.scene.extraupdate)
5000 R_ResetViewRendering2D();
5003 static const unsigned short bboxelements[36] =
5013 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5016 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5017 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5018 GL_DepthMask(false);
5019 GL_DepthRange(0, 1);
5020 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5021 R_Mesh_Matrix(&identitymatrix);
5022 R_Mesh_ResetTextureState();
5024 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5025 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5027 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5028 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5029 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5030 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5031 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5032 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5033 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5034 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5035 R_FillColors(color4f, 8, cr, cg, cb, ca);
5036 if (r_refdef.fogenabled)
5038 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5040 f1 = RSurf_FogVertex(v);
5042 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5043 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5044 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5047 R_Mesh_VertexPointer(vertex3f, 0, 0);
5048 R_Mesh_ColorPointer(color4f, 0, 0);
5049 R_Mesh_ResetTextureState();
5050 R_SetupGenericShader(false);
5051 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5054 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5058 prvm_edict_t *edict;
5059 prvm_prog_t *prog_save = prog;
5061 // this function draws bounding boxes of server entities
5065 GL_CullFace(GL_NONE);
5066 R_SetupGenericShader(false);
5070 for (i = 0;i < numsurfaces;i++)
5072 edict = PRVM_EDICT_NUM(surfacelist[i]);
5073 switch ((int)edict->fields.server->solid)
5075 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5076 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5077 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5078 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5079 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5080 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5082 color[3] *= r_showbboxes.value;
5083 color[3] = bound(0, color[3], 1);
5084 GL_DepthTest(!r_showdisabledepthtest.integer);
5085 GL_CullFace(r_refdef.view.cullface_front);
5086 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5092 static void R_DrawEntityBBoxes(void)
5095 prvm_edict_t *edict;
5097 prvm_prog_t *prog_save = prog;
5099 // this function draws bounding boxes of server entities
5105 for (i = 0;i < prog->num_edicts;i++)
5107 edict = PRVM_EDICT_NUM(i);
5108 if (edict->priv.server->free)
5110 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5111 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5113 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5115 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5116 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5122 unsigned short nomodelelements[24] =
5134 float nomodelvertex3f[6*3] =
5144 float nomodelcolor4f[6*4] =
5146 0.0f, 0.0f, 0.5f, 1.0f,
5147 0.0f, 0.0f, 0.5f, 1.0f,
5148 0.0f, 0.5f, 0.0f, 1.0f,
5149 0.0f, 0.5f, 0.0f, 1.0f,
5150 0.5f, 0.0f, 0.0f, 1.0f,
5151 0.5f, 0.0f, 0.0f, 1.0f
5154 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5160 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5161 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5163 // this is only called once per entity so numsurfaces is always 1, and
5164 // surfacelist is always {0}, so this code does not handle batches
5165 R_Mesh_Matrix(&ent->matrix);
5167 if (ent->flags & EF_ADDITIVE)
5169 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5170 GL_DepthMask(false);
5172 else if (ent->alpha < 1)
5174 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5175 GL_DepthMask(false);
5179 GL_BlendFunc(GL_ONE, GL_ZERO);
5182 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5183 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5184 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
5185 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5186 R_SetupGenericShader(false);
5187 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
5188 if (r_refdef.fogenabled)
5191 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5192 R_Mesh_ColorPointer(color4f, 0, 0);
5193 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5194 f1 = RSurf_FogVertex(org);
5196 for (i = 0, c = color4f;i < 6;i++, c += 4)
5198 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5199 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5200 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5204 else if (ent->alpha != 1)
5206 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5207 R_Mesh_ColorPointer(color4f, 0, 0);
5208 for (i = 0, c = color4f;i < 6;i++, c += 4)
5212 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
5213 R_Mesh_ResetTextureState();
5214 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
5217 void R_DrawNoModel(entity_render_t *ent)
5220 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5221 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
5222 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5224 // R_DrawNoModelCallback(ent, 0);
5227 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5229 vec3_t right1, right2, diff, normal;
5231 VectorSubtract (org2, org1, normal);
5233 // calculate 'right' vector for start
5234 VectorSubtract (r_refdef.view.origin, org1, diff);
5235 CrossProduct (normal, diff, right1);
5236 VectorNormalize (right1);
5238 // calculate 'right' vector for end
5239 VectorSubtract (r_refdef.view.origin, org2, diff);
5240 CrossProduct (normal, diff, right2);
5241 VectorNormalize (right2);
5243 vert[ 0] = org1[0] + width * right1[0];
5244 vert[ 1] = org1[1] + width * right1[1];
5245 vert[ 2] = org1[2] + width * right1[2];
5246 vert[ 3] = org1[0] - width * right1[0];
5247 vert[ 4] = org1[1] - width * right1[1];
5248 vert[ 5] = org1[2] - width * right1[2];
5249 vert[ 6] = org2[0] - width * right2[0];
5250 vert[ 7] = org2[1] - width * right2[1];
5251 vert[ 8] = org2[2] - width * right2[2];
5252 vert[ 9] = org2[0] + width * right2[0];
5253 vert[10] = org2[1] + width * right2[1];
5254 vert[11] = org2[2] + width * right2[2];
5257 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5259 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)
5261 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
5265 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5266 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5268 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
5269 fog = RSurf_FogVertex(origin);
5271 R_Mesh_Matrix(&identitymatrix);
5272 GL_BlendFunc(blendfunc1, blendfunc2);
5274 GL_CullFace(GL_NONE);
5276 GL_DepthMask(false);
5277 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5278 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5279 GL_DepthTest(!depthdisable);
5281 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5282 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5283 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5284 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5285 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5286 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5287 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5288 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5289 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5290 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5291 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5292 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5294 R_Mesh_VertexPointer(vertex3f, 0, 0);
5295 R_Mesh_ColorPointer(NULL, 0, 0);
5296 R_Mesh_ResetTextureState();
5297 R_SetupGenericShader(true);
5298 R_Mesh_TexBind(0, R_GetTexture(texture));
5299 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5300 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5301 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5302 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5304 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5306 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5307 GL_BlendFunc(blendfunc1, GL_ONE);
5309 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5310 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5314 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5319 VectorSet(v, x, y, z);
5320 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5321 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5323 if (i == mesh->numvertices)
5325 if (mesh->numvertices < mesh->maxvertices)
5327 VectorCopy(v, vertex3f);
5328 mesh->numvertices++;
5330 return mesh->numvertices;
5336 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5340 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5341 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5342 e = mesh->element3i + mesh->numtriangles * 3;
5343 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5345 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5346 if (mesh->numtriangles < mesh->maxtriangles)
5351 mesh->numtriangles++;
5353 element[1] = element[2];
5357 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5361 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5362 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5363 e = mesh->element3i + mesh->numtriangles * 3;
5364 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5366 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5367 if (mesh->numtriangles < mesh->maxtriangles)
5372 mesh->numtriangles++;
5374 element[1] = element[2];
5378 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5379 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5381 int planenum, planenum2;
5384 mplane_t *plane, *plane2;
5386 double temppoints[2][256*3];
5387 // figure out how large a bounding box we need to properly compute this brush
5389 for (w = 0;w < numplanes;w++)
5390 maxdist = max(maxdist, fabs(planes[w].dist));
5391 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5392 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5393 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5397 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5398 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5400 if (planenum2 == planenum)
5402 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);
5405 if (tempnumpoints < 3)
5407 // generate elements forming a triangle fan for this polygon
5408 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5412 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)
5414 texturelayer_t *layer;
5415 layer = t->currentlayers + t->currentnumlayers++;
5417 layer->depthmask = depthmask;
5418 layer->blendfunc1 = blendfunc1;
5419 layer->blendfunc2 = blendfunc2;
5420 layer->texture = texture;
5421 layer->texmatrix = *matrix;
5422 layer->color[0] = r * r_refdef.view.colorscale;
5423 layer->color[1] = g * r_refdef.view.colorscale;
5424 layer->color[2] = b * r_refdef.view.colorscale;
5425 layer->color[3] = a;
5428 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5431 index = parms[2] + r_refdef.scene.time * parms[3];
5432 index -= floor(index);
5436 case Q3WAVEFUNC_NONE:
5437 case Q3WAVEFUNC_NOISE:
5438 case Q3WAVEFUNC_COUNT:
5441 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5442 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5443 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5444 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5445 case Q3WAVEFUNC_TRIANGLE:
5447 f = index - floor(index);
5458 return (float)(parms[0] + parms[1] * f);
5461 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5466 matrix4x4_t matrix, temp;
5467 switch(tcmod->tcmod)
5471 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5472 matrix = r_waterscrollmatrix;
5474 matrix = identitymatrix;
5476 case Q3TCMOD_ENTITYTRANSLATE:
5477 // this is used in Q3 to allow the gamecode to control texcoord
5478 // scrolling on the entity, which is not supported in darkplaces yet.
5479 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5481 case Q3TCMOD_ROTATE:
5482 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5483 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5484 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5487 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5489 case Q3TCMOD_SCROLL:
5490 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5492 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5493 w = (int) tcmod->parms[0];
5494 h = (int) tcmod->parms[1];
5495 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5497 idx = (int) floor(f * w * h);
5498 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5500 case Q3TCMOD_STRETCH:
5501 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5502 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5504 case Q3TCMOD_TRANSFORM:
5505 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5506 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5507 VectorSet(tcmat + 6, 0 , 0 , 1);
5508 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5509 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5511 case Q3TCMOD_TURBULENT:
5512 // this is handled in the RSurf_PrepareVertices function
5513 matrix = identitymatrix;
5517 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5520 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5522 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5523 char name[MAX_QPATH];
5524 skinframe_t *skinframe;
5525 unsigned char pixels[296*194];
5526 strlcpy(cache->name, skinname, sizeof(cache->name));
5527 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5528 if (developer_loading.integer)
5529 Con_Printf("loading %s\n", name);
5530 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5531 if (!skinframe || !skinframe->base)
5534 fs_offset_t filesize;
5536 f = FS_LoadFile(name, tempmempool, true, &filesize);
5539 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5540 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5544 cache->skinframe = skinframe;
5547 texture_t *R_GetCurrentTexture(texture_t *t)
5550 const entity_render_t *ent = rsurface.entity;
5551 dp_model_t *model = ent->model;
5552 q3shaderinfo_layer_tcmod_t *tcmod;
5554 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5555 return t->currentframe;
5556 t->update_lastrenderframe = r_frame;
5557 t->update_lastrenderentity = (void *)ent;
5559 // switch to an alternate material if this is a q1bsp animated material
5561 texture_t *texture = t;
5562 int s = ent->skinnum;
5563 if ((unsigned int)s >= (unsigned int)model->numskins)
5565 if (model->skinscenes)
5567 if (model->skinscenes[s].framecount > 1)
5568 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5570 s = model->skinscenes[s].firstframe;
5573 t = t + s * model->num_surfaces;
5576 // use an alternate animation if the entity's frame is not 0,
5577 // and only if the texture has an alternate animation
5578 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
5579 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5581 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5583 texture->currentframe = t;
5586 // update currentskinframe to be a qw skin or animation frame
5587 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"))
5589 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5591 r_qwskincache_size = cl.maxclients;
5593 Mem_Free(r_qwskincache);
5594 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5596 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5597 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5598 t->currentskinframe = r_qwskincache[i].skinframe;
5599 if (t->currentskinframe == NULL)
5600 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5602 else if (t->numskinframes >= 2)
5603 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5604 if (t->backgroundnumskinframes >= 2)
5605 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
5607 t->currentmaterialflags = t->basematerialflags;
5608 t->currentalpha = ent->alpha;
5609 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5610 t->currentalpha *= r_wateralpha.value;
5611 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5612 t->currentalpha *= t->r_water_wateralpha;
5613 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5614 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5615 if (!(ent->flags & RENDER_LIGHT))
5616 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5617 else if (rsurface.modeltexcoordlightmap2f == NULL)
5619 // pick a model lighting mode
5620 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5621 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5623 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5625 if (ent->effects & EF_ADDITIVE)
5626 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5627 else if (t->currentalpha < 1)
5628 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5629 if (ent->effects & EF_DOUBLESIDED)
5630 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5631 if (ent->effects & EF_NODEPTHTEST)
5632 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5633 if (ent->flags & RENDER_VIEWMODEL)
5634 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5635 if (t->backgroundnumskinframes)
5636 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5637 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5639 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5640 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5643 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5645 // there is no tcmod
5646 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5648 t->currenttexmatrix = r_waterscrollmatrix;
5649 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5653 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5654 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5657 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5658 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5659 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5660 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5662 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5663 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5664 t->glosstexture = r_texture_black;
5665 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5666 t->backgroundglosstexture = r_texture_black;
5667 t->specularpower = r_shadow_glossexponent.value;
5668 // TODO: store reference values for these in the texture?
5669 t->specularscale = 0;
5670 if (r_shadow_gloss.integer > 0)
5672 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5674 if (r_shadow_glossintensity.value > 0)
5676 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5677 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5678 t->specularscale = r_shadow_glossintensity.value;
5681 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5683 t->glosstexture = r_texture_white;
5684 t->backgroundglosstexture = r_texture_white;
5685 t->specularscale = r_shadow_gloss2intensity.value;
5686 t->specularpower = r_shadow_gloss2exponent.value;
5689 t->specularscale *= t->specularscalemod;
5690 t->specularpower *= t->specularpowermod;
5692 // lightmaps mode looks bad with dlights using actual texturing, so turn
5693 // off the colormap and glossmap, but leave the normalmap on as it still
5694 // accurately represents the shading involved
5695 if (gl_lightmaps.integer)
5697 t->basetexture = r_texture_grey128;
5698 t->backgroundbasetexture = NULL;
5699 t->specularscale = 0;
5700 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5703 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5704 VectorClear(t->dlightcolor);
5705 t->currentnumlayers = 0;
5706 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5709 int blendfunc1, blendfunc2;
5711 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5713 blendfunc1 = GL_SRC_ALPHA;
5714 blendfunc2 = GL_ONE;
5716 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5718 blendfunc1 = GL_SRC_ALPHA;
5719 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5721 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5723 blendfunc1 = t->customblendfunc[0];
5724 blendfunc2 = t->customblendfunc[1];
5728 blendfunc1 = GL_ONE;
5729 blendfunc2 = GL_ZERO;
5731 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5732 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5733 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5734 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5736 // fullbright is not affected by r_refdef.lightmapintensity
5737 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]);
5738 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5739 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]);
5740 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5741 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]);
5745 vec3_t ambientcolor;
5747 // set the color tint used for lights affecting this surface
5748 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5750 // q3bsp has no lightmap updates, so the lightstylevalue that
5751 // would normally be baked into the lightmap must be
5752 // applied to the color
5753 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5754 if (ent->model->type == mod_brushq3)
5755 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5756 colorscale *= r_refdef.lightmapintensity;
5757 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5758 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5759 // basic lit geometry
5760 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]);
5761 // add pants/shirt if needed
5762 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5763 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]);
5764 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5765 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]);
5766 // now add ambient passes if needed
5767 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5769 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]);
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_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]);
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_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]);
5776 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5777 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]);
5778 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5780 // if this is opaque use alpha blend which will darken the earlier
5783 // if this is an alpha blended material, all the earlier passes
5784 // were darkened by fog already, so we only need to add the fog
5785 // color ontop through the fog mask texture
5787 // if this is an additive blended material, all the earlier passes
5788 // were darkened by fog already, and we should not add fog color
5789 // (because the background was not darkened, there is no fog color
5790 // that was lost behind it).
5791 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]);
5795 return t->currentframe;
5798 rsurfacestate_t rsurface;
5800 void R_Mesh_ResizeArrays(int newvertices)
5803 if (rsurface.array_size >= newvertices)
5805 if (rsurface.array_modelvertex3f)
5806 Mem_Free(rsurface.array_modelvertex3f);
5807 rsurface.array_size = (newvertices + 1023) & ~1023;
5808 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5809 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5810 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5811 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5812 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5813 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5814 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5815 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5816 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5817 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5818 rsurface.array_color4f = base + rsurface.array_size * 27;
5819 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5822 void RSurf_ActiveWorldEntity(void)
5824 dp_model_t *model = r_refdef.scene.worldmodel;
5825 //if (rsurface.entity == r_refdef.scene.worldentity)
5827 rsurface.entity = r_refdef.scene.worldentity;
5828 if (rsurface.array_size < model->surfmesh.num_vertices)
5829 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5830 rsurface.matrix = identitymatrix;
5831 rsurface.inversematrix = identitymatrix;
5832 R_Mesh_Matrix(&identitymatrix);
5833 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5834 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5835 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5836 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5837 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5838 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5839 VectorSet(rsurface.glowmod, 1, 1, 1);
5840 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5841 rsurface.frameblend[0].lerp = 1;
5842 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5843 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5844 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5845 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5846 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5847 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5848 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5849 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5850 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5851 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5852 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5853 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5854 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5855 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5856 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5857 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5858 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5859 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5860 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5861 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5862 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5863 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5864 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5865 rsurface.modelelement3i = model->surfmesh.data_element3i;
5866 rsurface.modelelement3s = model->surfmesh.data_element3s;
5867 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5868 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5869 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5870 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5871 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5872 rsurface.modelsurfaces = model->data_surfaces;
5873 rsurface.generatedvertex = false;
5874 rsurface.vertex3f = rsurface.modelvertex3f;
5875 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5876 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5877 rsurface.svector3f = rsurface.modelsvector3f;
5878 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5879 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5880 rsurface.tvector3f = rsurface.modeltvector3f;
5881 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5882 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5883 rsurface.normal3f = rsurface.modelnormal3f;
5884 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5885 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5886 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5889 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5891 dp_model_t *model = ent->model;
5892 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5894 rsurface.entity = (entity_render_t *)ent;
5895 if (rsurface.array_size < model->surfmesh.num_vertices)
5896 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5897 rsurface.matrix = ent->matrix;
5898 rsurface.inversematrix = ent->inversematrix;
5899 R_Mesh_Matrix(&rsurface.matrix);
5900 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
5901 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5902 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5903 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5904 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5905 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5906 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5907 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5908 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5909 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5910 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5911 VectorCopy(ent->glowmod, rsurface.glowmod);
5912 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5913 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5914 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5915 if (ent->model->brush.submodel)
5917 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5918 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5920 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5922 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5924 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5925 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5926 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5927 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5929 else if (wanttangents)
5931 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5932 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5933 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5934 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5935 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5937 else if (wantnormals)
5939 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5940 rsurface.modelsvector3f = NULL;
5941 rsurface.modeltvector3f = NULL;
5942 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5943 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5947 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5948 rsurface.modelsvector3f = NULL;
5949 rsurface.modeltvector3f = NULL;
5950 rsurface.modelnormal3f = NULL;
5951 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5953 rsurface.modelvertex3f_bufferobject = 0;
5954 rsurface.modelvertex3f_bufferoffset = 0;
5955 rsurface.modelsvector3f_bufferobject = 0;
5956 rsurface.modelsvector3f_bufferoffset = 0;
5957 rsurface.modeltvector3f_bufferobject = 0;
5958 rsurface.modeltvector3f_bufferoffset = 0;
5959 rsurface.modelnormal3f_bufferobject = 0;
5960 rsurface.modelnormal3f_bufferoffset = 0;
5961 rsurface.generatedvertex = true;
5965 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5966 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5967 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5968 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5969 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5970 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5971 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5972 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5973 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5974 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5975 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5976 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5977 rsurface.generatedvertex = false;
5979 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5980 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5981 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5982 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5983 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5984 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5985 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5986 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5987 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5988 rsurface.modelelement3i = model->surfmesh.data_element3i;
5989 rsurface.modelelement3s = model->surfmesh.data_element3s;
5990 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5991 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5992 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5993 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5994 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5995 rsurface.modelsurfaces = model->data_surfaces;
5996 rsurface.vertex3f = rsurface.modelvertex3f;
5997 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5998 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5999 rsurface.svector3f = rsurface.modelsvector3f;
6000 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6001 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6002 rsurface.tvector3f = rsurface.modeltvector3f;
6003 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6004 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6005 rsurface.normal3f = rsurface.modelnormal3f;
6006 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6007 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6008 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6011 float RSurf_FogVertex(const float *v)
6013 float len = VectorDistance(rsurface.localvieworigin, v);
6014 unsigned int fogmasktableindex;
6015 fogmasktableindex = (unsigned int)(len * r_refdef.fogmasktabledistmultiplier);
6016 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6019 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6020 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
6023 int texturesurfaceindex;
6028 const float *v1, *in_tc;
6030 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6032 q3shaderinfo_deform_t *deform;
6033 // 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
6034 if (rsurface.generatedvertex)
6036 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6037 generatenormals = true;
6038 for (i = 0;i < Q3MAXDEFORMS;i++)
6040 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6042 generatetangents = true;
6043 generatenormals = true;
6045 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6046 generatenormals = true;
6048 if (generatenormals && !rsurface.modelnormal3f)
6050 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6051 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6052 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6053 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6055 if (generatetangents && !rsurface.modelsvector3f)
6057 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6058 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6059 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6060 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6061 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6062 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6063 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);
6066 rsurface.vertex3f = rsurface.modelvertex3f;
6067 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6068 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6069 rsurface.svector3f = rsurface.modelsvector3f;
6070 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6071 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6072 rsurface.tvector3f = rsurface.modeltvector3f;
6073 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6074 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6075 rsurface.normal3f = rsurface.modelnormal3f;
6076 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6077 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6078 // if vertices are deformed (sprite flares and things in maps, possibly
6079 // water waves, bulges and other deformations), generate them into
6080 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6081 // (may be static model data or generated data for an animated model, or
6082 // the previous deform pass)
6083 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6085 switch (deform->deform)
6088 case Q3DEFORM_PROJECTIONSHADOW:
6089 case Q3DEFORM_TEXT0:
6090 case Q3DEFORM_TEXT1:
6091 case Q3DEFORM_TEXT2:
6092 case Q3DEFORM_TEXT3:
6093 case Q3DEFORM_TEXT4:
6094 case Q3DEFORM_TEXT5:
6095 case Q3DEFORM_TEXT6:
6096 case Q3DEFORM_TEXT7:
6099 case Q3DEFORM_AUTOSPRITE:
6100 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6101 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6102 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6103 VectorNormalize(newforward);
6104 VectorNormalize(newright);
6105 VectorNormalize(newup);
6106 // make deformed versions of only the model vertices used by the specified surfaces
6107 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6109 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6110 // a single autosprite surface can contain multiple sprites...
6111 for (j = 0;j < surface->num_vertices - 3;j += 4)
6113 VectorClear(center);
6114 for (i = 0;i < 4;i++)
6115 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6116 VectorScale(center, 0.25f, center);
6117 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6118 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6119 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6120 for (i = 0;i < 4;i++)
6122 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6123 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6126 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);
6127 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);
6129 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6130 rsurface.vertex3f_bufferobject = 0;
6131 rsurface.vertex3f_bufferoffset = 0;
6132 rsurface.svector3f = rsurface.array_deformedsvector3f;
6133 rsurface.svector3f_bufferobject = 0;
6134 rsurface.svector3f_bufferoffset = 0;
6135 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6136 rsurface.tvector3f_bufferobject = 0;
6137 rsurface.tvector3f_bufferoffset = 0;
6138 rsurface.normal3f = rsurface.array_deformednormal3f;
6139 rsurface.normal3f_bufferobject = 0;
6140 rsurface.normal3f_bufferoffset = 0;
6142 case Q3DEFORM_AUTOSPRITE2:
6143 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6144 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6145 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6146 VectorNormalize(newforward);
6147 VectorNormalize(newright);
6148 VectorNormalize(newup);
6149 // make deformed versions of only the model vertices used by the specified surfaces
6150 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6152 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6153 const float *v1, *v2;
6163 memset(shortest, 0, sizeof(shortest));
6164 // a single autosprite surface can contain multiple sprites...
6165 for (j = 0;j < surface->num_vertices - 3;j += 4)
6167 VectorClear(center);
6168 for (i = 0;i < 4;i++)
6169 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6170 VectorScale(center, 0.25f, center);
6171 // find the two shortest edges, then use them to define the
6172 // axis vectors for rotating around the central axis
6173 for (i = 0;i < 6;i++)
6175 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6176 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6178 Debug_PolygonBegin(NULL, 0);
6179 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6180 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);
6181 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6184 l = VectorDistance2(v1, v2);
6185 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6187 l += (1.0f / 1024.0f);
6188 if (shortest[0].length2 > l || i == 0)
6190 shortest[1] = shortest[0];
6191 shortest[0].length2 = l;
6192 shortest[0].v1 = v1;
6193 shortest[0].v2 = v2;
6195 else if (shortest[1].length2 > l || i == 1)
6197 shortest[1].length2 = l;
6198 shortest[1].v1 = v1;
6199 shortest[1].v2 = v2;
6202 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6203 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6205 Debug_PolygonBegin(NULL, 0);
6206 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6207 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);
6208 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6211 // this calculates the right vector from the shortest edge
6212 // and the up vector from the edge midpoints
6213 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6214 VectorNormalize(right);
6215 VectorSubtract(end, start, up);
6216 VectorNormalize(up);
6217 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6218 VectorSubtract(rsurface.localvieworigin, center, forward);
6219 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6220 VectorNegate(forward, forward);
6221 VectorReflect(forward, 0, up, forward);
6222 VectorNormalize(forward);
6223 CrossProduct(up, forward, newright);
6224 VectorNormalize(newright);
6226 Debug_PolygonBegin(NULL, 0);
6227 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);
6228 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6229 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6233 Debug_PolygonBegin(NULL, 0);
6234 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6235 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6236 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6239 // rotate the quad around the up axis vector, this is made
6240 // especially easy by the fact we know the quad is flat,
6241 // so we only have to subtract the center position and
6242 // measure distance along the right vector, and then
6243 // multiply that by the newright vector and add back the
6245 // we also need to subtract the old position to undo the
6246 // displacement from the center, which we do with a
6247 // DotProduct, the subtraction/addition of center is also
6248 // optimized into DotProducts here
6249 l = DotProduct(right, center);
6250 for (i = 0;i < 4;i++)
6252 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6253 f = DotProduct(right, v1) - l;
6254 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6257 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);
6258 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);
6260 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6261 rsurface.vertex3f_bufferobject = 0;
6262 rsurface.vertex3f_bufferoffset = 0;
6263 rsurface.svector3f = rsurface.array_deformedsvector3f;
6264 rsurface.svector3f_bufferobject = 0;
6265 rsurface.svector3f_bufferoffset = 0;
6266 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6267 rsurface.tvector3f_bufferobject = 0;
6268 rsurface.tvector3f_bufferoffset = 0;
6269 rsurface.normal3f = rsurface.array_deformednormal3f;
6270 rsurface.normal3f_bufferobject = 0;
6271 rsurface.normal3f_bufferoffset = 0;
6273 case Q3DEFORM_NORMAL:
6274 // deform the normals to make reflections wavey
6275 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6277 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6278 for (j = 0;j < surface->num_vertices;j++)
6281 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6282 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6283 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6284 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6285 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6286 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6287 VectorNormalize(normal);
6289 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
6291 rsurface.svector3f = rsurface.array_deformedsvector3f;
6292 rsurface.svector3f_bufferobject = 0;
6293 rsurface.svector3f_bufferoffset = 0;
6294 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6295 rsurface.tvector3f_bufferobject = 0;
6296 rsurface.tvector3f_bufferoffset = 0;
6297 rsurface.normal3f = rsurface.array_deformednormal3f;
6298 rsurface.normal3f_bufferobject = 0;
6299 rsurface.normal3f_bufferoffset = 0;
6302 // deform vertex array to make wavey water and flags and such
6303 waveparms[0] = deform->waveparms[0];
6304 waveparms[1] = deform->waveparms[1];
6305 waveparms[2] = deform->waveparms[2];
6306 waveparms[3] = deform->waveparms[3];
6307 // this is how a divisor of vertex influence on deformation
6308 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6309 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6310 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6312 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6313 for (j = 0;j < surface->num_vertices;j++)
6315 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6316 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6317 // if the wavefunc depends on time, evaluate it per-vertex
6320 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6321 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6323 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6326 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6327 rsurface.vertex3f_bufferobject = 0;
6328 rsurface.vertex3f_bufferoffset = 0;
6330 case Q3DEFORM_BULGE:
6331 // deform vertex array to make the surface have moving bulges
6332 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6334 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6335 for (j = 0;j < surface->num_vertices;j++)
6337 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6338 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6341 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6342 rsurface.vertex3f_bufferobject = 0;
6343 rsurface.vertex3f_bufferoffset = 0;
6346 // deform vertex array
6347 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6348 VectorScale(deform->parms, scale, waveparms);
6349 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6351 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6352 for (j = 0;j < surface->num_vertices;j++)
6353 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6355 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6356 rsurface.vertex3f_bufferobject = 0;
6357 rsurface.vertex3f_bufferoffset = 0;
6361 // generate texcoords based on the chosen texcoord source
6362 switch(rsurface.texture->tcgen.tcgen)
6365 case Q3TCGEN_TEXTURE:
6366 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6367 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6368 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6370 case Q3TCGEN_LIGHTMAP:
6371 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6372 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6373 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6375 case Q3TCGEN_VECTOR:
6376 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6378 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6379 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)
6381 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6382 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6385 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6386 rsurface.texcoordtexture2f_bufferobject = 0;
6387 rsurface.texcoordtexture2f_bufferoffset = 0;
6389 case Q3TCGEN_ENVIRONMENT:
6390 // make environment reflections using a spheremap
6391 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6393 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6394 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6395 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6396 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6397 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6399 // identical to Q3A's method, but executed in worldspace so
6400 // carried models can be shiny too
6402 float viewer[3], d, reflected[3], worldreflected[3];
6404 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6405 // VectorNormalize(viewer);
6407 d = DotProduct(normal, viewer);
6409 reflected[0] = normal[0]*2*d - viewer[0];
6410 reflected[1] = normal[1]*2*d - viewer[1];
6411 reflected[2] = normal[2]*2*d - viewer[2];
6412 // note: this is proportinal to viewer, so we can normalize later
6414 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6415 VectorNormalize(worldreflected);
6417 // note: this sphere map only uses world x and z!
6418 // so positive and negative y will LOOK THE SAME.
6419 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6420 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6423 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6424 rsurface.texcoordtexture2f_bufferobject = 0;
6425 rsurface.texcoordtexture2f_bufferoffset = 0;
6428 // the only tcmod that needs software vertex processing is turbulent, so
6429 // check for it here and apply the changes if needed
6430 // and we only support that as the first one
6431 // (handling a mixture of turbulent and other tcmods would be problematic
6432 // without punting it entirely to a software path)
6433 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6435 amplitude = rsurface.texture->tcmods[0].parms[1];
6436 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6437 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6439 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6440 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)
6442 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6443 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6446 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6447 rsurface.texcoordtexture2f_bufferobject = 0;
6448 rsurface.texcoordtexture2f_bufferoffset = 0;
6450 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6451 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6452 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6453 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6456 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6459 const msurface_t *surface = texturesurfacelist[0];
6460 const msurface_t *surface2;
6465 // TODO: lock all array ranges before render, rather than on each surface
6466 if (texturenumsurfaces == 1)
6468 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6469 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);
6471 else if (r_batchmode.integer == 2)
6473 #define MAXBATCHTRIANGLES 4096
6474 int batchtriangles = 0;
6475 int batchelements[MAXBATCHTRIANGLES*3];
6476 for (i = 0;i < texturenumsurfaces;i = j)
6478 surface = texturesurfacelist[i];
6480 if (surface->num_triangles > MAXBATCHTRIANGLES)
6482 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);
6485 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6486 batchtriangles = surface->num_triangles;
6487 firstvertex = surface->num_firstvertex;
6488 endvertex = surface->num_firstvertex + surface->num_vertices;
6489 for (;j < texturenumsurfaces;j++)
6491 surface2 = texturesurfacelist[j];
6492 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6494 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6495 batchtriangles += surface2->num_triangles;
6496 firstvertex = min(firstvertex, surface2->num_firstvertex);
6497 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6499 surface2 = texturesurfacelist[j-1];
6500 numvertices = endvertex - firstvertex;
6501 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6504 else if (r_batchmode.integer == 1)
6506 for (i = 0;i < texturenumsurfaces;i = j)
6508 surface = texturesurfacelist[i];
6509 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6510 if (texturesurfacelist[j] != surface2)
6512 surface2 = texturesurfacelist[j-1];
6513 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6514 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6515 GL_LockArrays(surface->num_firstvertex, numvertices);
6516 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6521 for (i = 0;i < texturenumsurfaces;i++)
6523 surface = texturesurfacelist[i];
6524 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6525 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);
6530 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6532 int i, planeindex, vertexindex;
6536 r_waterstate_waterplane_t *p, *bestp;
6537 msurface_t *surface;
6538 if (r_waterstate.renderingscene)
6540 for (i = 0;i < texturenumsurfaces;i++)
6542 surface = texturesurfacelist[i];
6543 if (lightmaptexunit >= 0)
6544 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6545 if (deluxemaptexunit >= 0)
6546 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6547 // pick the closest matching water plane
6550 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6553 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6555 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6556 d += fabs(PlaneDiff(vert, &p->plane));
6558 if (bestd > d || !bestp)
6566 if (refractiontexunit >= 0)
6567 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6568 if (reflectiontexunit >= 0)
6569 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6573 if (refractiontexunit >= 0)
6574 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6575 if (reflectiontexunit >= 0)
6576 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6578 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6579 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);
6583 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6587 const msurface_t *surface = texturesurfacelist[0];
6588 const msurface_t *surface2;
6593 // TODO: lock all array ranges before render, rather than on each surface
6594 if (texturenumsurfaces == 1)
6596 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6597 if (deluxemaptexunit >= 0)
6598 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6599 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6600 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);
6602 else if (r_batchmode.integer == 2)
6604 #define MAXBATCHTRIANGLES 4096
6605 int batchtriangles = 0;
6606 int batchelements[MAXBATCHTRIANGLES*3];
6607 for (i = 0;i < texturenumsurfaces;i = j)
6609 surface = texturesurfacelist[i];
6610 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6611 if (deluxemaptexunit >= 0)
6612 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6614 if (surface->num_triangles > MAXBATCHTRIANGLES)
6616 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);
6619 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6620 batchtriangles = surface->num_triangles;
6621 firstvertex = surface->num_firstvertex;
6622 endvertex = surface->num_firstvertex + surface->num_vertices;
6623 for (;j < texturenumsurfaces;j++)
6625 surface2 = texturesurfacelist[j];
6626 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6628 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6629 batchtriangles += surface2->num_triangles;
6630 firstvertex = min(firstvertex, surface2->num_firstvertex);
6631 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6633 surface2 = texturesurfacelist[j-1];
6634 numvertices = endvertex - firstvertex;
6635 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6638 else if (r_batchmode.integer == 1)
6641 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6642 for (i = 0;i < texturenumsurfaces;i = j)
6644 surface = texturesurfacelist[i];
6645 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6646 if (texturesurfacelist[j] != surface2)
6648 Con_Printf(" %i", j - i);
6651 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6653 for (i = 0;i < texturenumsurfaces;i = j)
6655 surface = texturesurfacelist[i];
6656 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6657 if (deluxemaptexunit >= 0)
6658 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6659 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6660 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6663 Con_Printf(" %i", j - i);
6665 surface2 = texturesurfacelist[j-1];
6666 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6667 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6668 GL_LockArrays(surface->num_firstvertex, numvertices);
6669 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6677 for (i = 0;i < texturenumsurfaces;i++)
6679 surface = texturesurfacelist[i];
6680 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6681 if (deluxemaptexunit >= 0)
6682 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6683 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6684 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);
6689 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6692 int texturesurfaceindex;
6693 if (r_showsurfaces.integer == 2)
6695 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6697 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6698 for (j = 0;j < surface->num_triangles;j++)
6700 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6701 GL_Color(f, f, f, 1);
6702 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6708 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6710 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6711 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6712 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);
6713 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6714 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);
6719 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6721 int texturesurfaceindex;
6724 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6726 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6727 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)
6735 rsurface.lightmapcolor4f = rsurface.array_color4f;
6736 rsurface.lightmapcolor4f_bufferobject = 0;
6737 rsurface.lightmapcolor4f_bufferoffset = 0;
6740 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6742 int texturesurfaceindex;
6746 if (rsurface.lightmapcolor4f)
6748 // generate color arrays for the surfaces in this list
6749 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6751 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6752 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)
6754 f = RSurf_FogVertex(v);
6764 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6766 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6767 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)
6769 f = RSurf_FogVertex(v);
6777 rsurface.lightmapcolor4f = rsurface.array_color4f;
6778 rsurface.lightmapcolor4f_bufferobject = 0;
6779 rsurface.lightmapcolor4f_bufferoffset = 0;
6782 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6784 int texturesurfaceindex;
6788 if (!rsurface.lightmapcolor4f)
6790 // generate color arrays for the surfaces in this list
6791 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6793 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6794 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)
6796 f = RSurf_FogVertex(v);
6797 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6798 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6799 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6803 rsurface.lightmapcolor4f = rsurface.array_color4f;
6804 rsurface.lightmapcolor4f_bufferobject = 0;
6805 rsurface.lightmapcolor4f_bufferoffset = 0;
6808 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6810 int texturesurfaceindex;
6813 if (!rsurface.lightmapcolor4f)
6815 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6817 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6818 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)
6826 rsurface.lightmapcolor4f = rsurface.array_color4f;
6827 rsurface.lightmapcolor4f_bufferobject = 0;
6828 rsurface.lightmapcolor4f_bufferoffset = 0;
6831 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6833 int texturesurfaceindex;
6836 if (!rsurface.lightmapcolor4f)
6838 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6840 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6841 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)
6843 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6844 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6845 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6849 rsurface.lightmapcolor4f = rsurface.array_color4f;
6850 rsurface.lightmapcolor4f_bufferobject = 0;
6851 rsurface.lightmapcolor4f_bufferoffset = 0;
6854 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6857 rsurface.lightmapcolor4f = NULL;
6858 rsurface.lightmapcolor4f_bufferobject = 0;
6859 rsurface.lightmapcolor4f_bufferoffset = 0;
6860 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6861 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6862 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6863 GL_Color(r, g, b, a);
6864 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6867 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6869 // TODO: optimize applyfog && applycolor case
6870 // just apply fog if necessary, and tint the fog color array if necessary
6871 rsurface.lightmapcolor4f = NULL;
6872 rsurface.lightmapcolor4f_bufferobject = 0;
6873 rsurface.lightmapcolor4f_bufferoffset = 0;
6874 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6875 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6876 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6877 GL_Color(r, g, b, a);
6878 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6881 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6883 int texturesurfaceindex;
6887 if (texturesurfacelist[0]->lightmapinfo)
6889 // generate color arrays for the surfaces in this list
6890 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6892 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6893 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6895 if (surface->lightmapinfo->samples)
6897 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6898 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6899 VectorScale(lm, scale, c);
6900 if (surface->lightmapinfo->styles[1] != 255)
6902 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6904 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6905 VectorMA(c, scale, lm, c);
6906 if (surface->lightmapinfo->styles[2] != 255)
6909 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6910 VectorMA(c, scale, lm, c);
6911 if (surface->lightmapinfo->styles[3] != 255)
6914 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6915 VectorMA(c, scale, lm, c);
6925 rsurface.lightmapcolor4f = rsurface.array_color4f;
6926 rsurface.lightmapcolor4f_bufferobject = 0;
6927 rsurface.lightmapcolor4f_bufferoffset = 0;
6931 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6932 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6933 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6935 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6936 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6937 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6938 GL_Color(r, g, b, a);
6939 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6942 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6944 int texturesurfaceindex;
6947 float *v, *c, *c2, alpha;
6948 vec3_t ambientcolor;
6949 vec3_t diffusecolor;
6953 VectorCopy(rsurface.modellight_lightdir, lightdir);
6954 f = 0.5f * r_refdef.lightmapintensity;
6955 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6956 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6957 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6958 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6959 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6960 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6962 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6964 // generate color arrays for the surfaces in this list
6965 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6967 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6968 int numverts = surface->num_vertices;
6969 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6970 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6971 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6972 // q3-style directional shading
6973 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6975 if ((f = DotProduct(c2, lightdir)) > 0)
6976 VectorMA(ambientcolor, f, diffusecolor, c);
6978 VectorCopy(ambientcolor, c);
6986 rsurface.lightmapcolor4f = rsurface.array_color4f;
6987 rsurface.lightmapcolor4f_bufferobject = 0;
6988 rsurface.lightmapcolor4f_bufferoffset = 0;
6989 *applycolor = false;
6993 *r = ambientcolor[0];
6994 *g = ambientcolor[1];
6995 *b = ambientcolor[2];
6996 rsurface.lightmapcolor4f = NULL;
6997 rsurface.lightmapcolor4f_bufferobject = 0;
6998 rsurface.lightmapcolor4f_bufferoffset = 0;
7002 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7004 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7005 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7006 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7007 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7008 GL_Color(r, g, b, a);
7009 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7012 void RSurf_SetupDepthAndCulling(void)
7014 // submodels are biased to avoid z-fighting with world surfaces that they
7015 // may be exactly overlapping (avoids z-fighting artifacts on certain
7016 // doors and things in Quake maps)
7017 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7018 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7019 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7020 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7023 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
7025 // transparent sky would be ridiculous
7026 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7028 R_SetupGenericShader(false);
7031 skyrendernow = false;
7032 // we have to force off the water clipping plane while rendering sky
7036 // restore entity matrix
7037 R_Mesh_Matrix(&rsurface.matrix);
7039 RSurf_SetupDepthAndCulling();
7041 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7042 // skymasking on them, and Quake3 never did sky masking (unlike
7043 // software Quake and software Quake2), so disable the sky masking
7044 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7045 // and skymasking also looks very bad when noclipping outside the
7046 // level, so don't use it then either.
7047 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7049 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7050 R_Mesh_ColorPointer(NULL, 0, 0);
7051 R_Mesh_ResetTextureState();
7052 if (skyrendermasked)
7054 R_SetupDepthOrShadowShader();
7055 // depth-only (masking)
7056 GL_ColorMask(0,0,0,0);
7057 // just to make sure that braindead drivers don't draw
7058 // anything despite that colormask...
7059 GL_BlendFunc(GL_ZERO, GL_ONE);
7063 R_SetupGenericShader(false);
7065 GL_BlendFunc(GL_ONE, GL_ZERO);
7067 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7068 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7069 if (skyrendermasked)
7070 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7072 R_Mesh_ResetTextureState();
7073 GL_Color(1, 1, 1, 1);
7076 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7078 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7081 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7082 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7083 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7084 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7085 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7086 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7087 if (rsurface.texture->backgroundcurrentskinframe)
7089 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7090 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7091 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7092 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7094 if(rsurface.texture->colormapping)
7096 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7097 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7099 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7100 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7101 R_Mesh_ColorPointer(NULL, 0, 0);
7103 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7105 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7107 // render background
7108 GL_BlendFunc(GL_ONE, GL_ZERO);
7110 GL_AlphaTest(false);
7112 GL_Color(1, 1, 1, 1);
7113 R_Mesh_ColorPointer(NULL, 0, 0);
7115 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7116 if (r_glsl_permutation)
7118 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7119 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7120 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7121 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7122 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7123 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7124 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);
7126 GL_LockArrays(0, 0);
7128 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7129 GL_DepthMask(false);
7130 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7131 R_Mesh_ColorPointer(NULL, 0, 0);
7133 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7134 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7135 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7138 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7139 if (!r_glsl_permutation)
7142 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7143 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7144 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7145 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7146 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7147 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7149 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7151 GL_BlendFunc(GL_ONE, GL_ZERO);
7153 GL_AlphaTest(false);
7157 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7158 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7159 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7162 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7164 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7165 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);
7167 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7171 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7172 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);
7174 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7176 GL_LockArrays(0, 0);
7179 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7181 // OpenGL 1.3 path - anything not completely ancient
7182 int texturesurfaceindex;
7183 qboolean applycolor;
7187 const texturelayer_t *layer;
7188 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7190 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7193 int layertexrgbscale;
7194 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7196 if (layerindex == 0)
7200 GL_AlphaTest(false);
7201 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7204 GL_DepthMask(layer->depthmask && writedepth);
7205 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7206 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7208 layertexrgbscale = 4;
7209 VectorScale(layer->color, 0.25f, layercolor);
7211 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7213 layertexrgbscale = 2;
7214 VectorScale(layer->color, 0.5f, layercolor);
7218 layertexrgbscale = 1;
7219 VectorScale(layer->color, 1.0f, layercolor);
7221 layercolor[3] = layer->color[3];
7222 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7223 R_Mesh_ColorPointer(NULL, 0, 0);
7224 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7225 switch (layer->type)
7227 case TEXTURELAYERTYPE_LITTEXTURE:
7228 memset(&m, 0, sizeof(m));
7229 m.tex[0] = R_GetTexture(r_texture_white);
7230 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7231 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7232 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7233 m.tex[1] = R_GetTexture(layer->texture);
7234 m.texmatrix[1] = layer->texmatrix;
7235 m.texrgbscale[1] = layertexrgbscale;
7236 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7237 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7238 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7239 R_Mesh_TextureState(&m);
7240 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7241 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7242 else if (rsurface.uselightmaptexture)
7243 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7245 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7247 case TEXTURELAYERTYPE_TEXTURE:
7248 memset(&m, 0, sizeof(m));
7249 m.tex[0] = R_GetTexture(layer->texture);
7250 m.texmatrix[0] = layer->texmatrix;
7251 m.texrgbscale[0] = layertexrgbscale;
7252 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7253 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7254 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7255 R_Mesh_TextureState(&m);
7256 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7258 case TEXTURELAYERTYPE_FOG:
7259 memset(&m, 0, sizeof(m));
7260 m.texrgbscale[0] = layertexrgbscale;
7263 m.tex[0] = R_GetTexture(layer->texture);
7264 m.texmatrix[0] = layer->texmatrix;
7265 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7266 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7267 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7269 R_Mesh_TextureState(&m);
7270 // generate a color array for the fog pass
7271 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7272 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7276 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7277 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)
7279 f = 1 - RSurf_FogVertex(v);
7280 c[0] = layercolor[0];
7281 c[1] = layercolor[1];
7282 c[2] = layercolor[2];
7283 c[3] = f * layercolor[3];
7286 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7289 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7291 GL_LockArrays(0, 0);
7294 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7296 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7297 GL_AlphaTest(false);
7301 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7303 // OpenGL 1.1 - crusty old voodoo path
7304 int texturesurfaceindex;
7308 const texturelayer_t *layer;
7309 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7311 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7313 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7315 if (layerindex == 0)
7319 GL_AlphaTest(false);
7320 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7323 GL_DepthMask(layer->depthmask && writedepth);
7324 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7325 R_Mesh_ColorPointer(NULL, 0, 0);
7326 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7327 switch (layer->type)
7329 case TEXTURELAYERTYPE_LITTEXTURE:
7330 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7332 // two-pass lit texture with 2x rgbscale
7333 // first the lightmap pass
7334 memset(&m, 0, sizeof(m));
7335 m.tex[0] = R_GetTexture(r_texture_white);
7336 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7337 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7338 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7339 R_Mesh_TextureState(&m);
7340 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7341 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7342 else if (rsurface.uselightmaptexture)
7343 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7345 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7346 GL_LockArrays(0, 0);
7347 // then apply the texture to it
7348 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7349 memset(&m, 0, sizeof(m));
7350 m.tex[0] = R_GetTexture(layer->texture);
7351 m.texmatrix[0] = layer->texmatrix;
7352 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7353 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7354 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7355 R_Mesh_TextureState(&m);
7356 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);
7360 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7361 memset(&m, 0, sizeof(m));
7362 m.tex[0] = R_GetTexture(layer->texture);
7363 m.texmatrix[0] = layer->texmatrix;
7364 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7365 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7366 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7367 R_Mesh_TextureState(&m);
7368 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7369 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);
7371 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);
7374 case TEXTURELAYERTYPE_TEXTURE:
7375 // singletexture unlit texture with transparency support
7376 memset(&m, 0, sizeof(m));
7377 m.tex[0] = R_GetTexture(layer->texture);
7378 m.texmatrix[0] = layer->texmatrix;
7379 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7380 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7381 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7382 R_Mesh_TextureState(&m);
7383 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);
7385 case TEXTURELAYERTYPE_FOG:
7386 // singletexture fogging
7387 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7390 memset(&m, 0, sizeof(m));
7391 m.tex[0] = R_GetTexture(layer->texture);
7392 m.texmatrix[0] = layer->texmatrix;
7393 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7394 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7395 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7396 R_Mesh_TextureState(&m);
7399 R_Mesh_ResetTextureState();
7400 // generate a color array for the fog pass
7401 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7405 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7406 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)
7408 f = 1 - RSurf_FogVertex(v);
7409 c[0] = layer->color[0];
7410 c[1] = layer->color[1];
7411 c[2] = layer->color[2];
7412 c[3] = f * layer->color[3];
7415 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7418 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7420 GL_LockArrays(0, 0);
7423 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7425 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7426 GL_AlphaTest(false);
7430 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7434 GL_AlphaTest(false);
7435 R_Mesh_ColorPointer(NULL, 0, 0);
7436 R_Mesh_ResetTextureState();
7437 R_SetupGenericShader(false);
7439 if(rsurface.texture && rsurface.texture->currentskinframe)
7441 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7442 c[3] *= rsurface.texture->currentalpha;
7452 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7454 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7455 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7456 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7459 // brighten it up (as texture value 127 means "unlit")
7460 c[0] *= 2 * r_refdef.view.colorscale;
7461 c[1] *= 2 * r_refdef.view.colorscale;
7462 c[2] *= 2 * r_refdef.view.colorscale;
7464 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7465 c[3] *= r_wateralpha.value;
7467 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7469 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7470 GL_DepthMask(false);
7472 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7474 GL_BlendFunc(GL_ONE, GL_ONE);
7475 GL_DepthMask(false);
7477 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7479 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7480 GL_DepthMask(false);
7482 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7484 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7485 GL_DepthMask(false);
7489 GL_BlendFunc(GL_ONE, GL_ZERO);
7490 GL_DepthMask(writedepth);
7493 rsurface.lightmapcolor4f = NULL;
7495 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7497 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7499 rsurface.lightmapcolor4f = NULL;
7500 rsurface.lightmapcolor4f_bufferobject = 0;
7501 rsurface.lightmapcolor4f_bufferoffset = 0;
7503 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7505 qboolean applycolor = true;
7508 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7510 r_refdef.lightmapintensity = 1;
7511 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7512 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7516 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7518 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7519 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7520 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7523 if(!rsurface.lightmapcolor4f)
7524 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7526 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7527 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7528 if(r_refdef.fogenabled)
7529 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7531 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7532 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7535 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7538 RSurf_SetupDepthAndCulling();
7539 if (r_showsurfaces.integer == 3)
7540 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7541 else if (r_glsl.integer && gl_support_fragment_shader)
7542 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7543 else if (gl_combine.integer && r_textureunits.integer >= 2)
7544 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7546 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7550 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7553 RSurf_SetupDepthAndCulling();
7554 if (r_showsurfaces.integer == 3)
7555 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7556 else if (r_glsl.integer && gl_support_fragment_shader)
7557 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7558 else if (gl_combine.integer && r_textureunits.integer >= 2)
7559 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7561 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7565 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7568 int texturenumsurfaces, endsurface;
7570 msurface_t *surface;
7571 msurface_t *texturesurfacelist[1024];
7573 // if the model is static it doesn't matter what value we give for
7574 // wantnormals and wanttangents, so this logic uses only rules applicable
7575 // to a model, knowing that they are meaningless otherwise
7576 if (ent == r_refdef.scene.worldentity)
7577 RSurf_ActiveWorldEntity();
7578 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7579 RSurf_ActiveModelEntity(ent, false, false);
7581 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7583 for (i = 0;i < numsurfaces;i = j)
7586 surface = rsurface.modelsurfaces + surfacelist[i];
7587 texture = surface->texture;
7588 rsurface.texture = R_GetCurrentTexture(texture);
7589 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7590 // scan ahead until we find a different texture
7591 endsurface = min(i + 1024, numsurfaces);
7592 texturenumsurfaces = 0;
7593 texturesurfacelist[texturenumsurfaces++] = surface;
7594 for (;j < endsurface;j++)
7596 surface = rsurface.modelsurfaces + surfacelist[j];
7597 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7599 texturesurfacelist[texturenumsurfaces++] = surface;
7601 // render the range of surfaces
7602 if (ent == r_refdef.scene.worldentity)
7603 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7605 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7607 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7608 GL_AlphaTest(false);
7611 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7613 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7617 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7619 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7621 RSurf_SetupDepthAndCulling();
7622 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7623 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7625 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7627 RSurf_SetupDepthAndCulling();
7628 GL_AlphaTest(false);
7629 R_Mesh_ColorPointer(NULL, 0, 0);
7630 R_Mesh_ResetTextureState();
7631 R_SetupGenericShader(false);
7632 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7634 GL_BlendFunc(GL_ONE, GL_ZERO);
7635 GL_Color(0, 0, 0, 1);
7636 GL_DepthTest(writedepth);
7637 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7639 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7641 RSurf_SetupDepthAndCulling();
7642 GL_AlphaTest(false);
7643 R_Mesh_ColorPointer(NULL, 0, 0);
7644 R_Mesh_ResetTextureState();
7645 R_SetupGenericShader(false);
7646 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7648 GL_BlendFunc(GL_ONE, GL_ZERO);
7650 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7652 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7653 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7654 else if (!rsurface.texture->currentnumlayers)
7656 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7658 // transparent surfaces get pushed off into the transparent queue
7659 int surfacelistindex;
7660 const msurface_t *surface;
7661 vec3_t tempcenter, center;
7662 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7664 surface = texturesurfacelist[surfacelistindex];
7665 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7666 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7667 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7668 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7669 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7674 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7675 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7680 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7684 // break the surface list down into batches by texture and use of lightmapping
7685 for (i = 0;i < numsurfaces;i = j)
7688 // texture is the base texture pointer, rsurface.texture is the
7689 // current frame/skin the texture is directing us to use (for example
7690 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7691 // use skin 1 instead)
7692 texture = surfacelist[i]->texture;
7693 rsurface.texture = R_GetCurrentTexture(texture);
7694 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7695 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7697 // if this texture is not the kind we want, skip ahead to the next one
7698 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7702 // simply scan ahead until we find a different texture or lightmap state
7703 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7705 // render the range of surfaces
7706 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7710 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7715 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7717 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7719 RSurf_SetupDepthAndCulling();
7720 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7721 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7723 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7725 RSurf_SetupDepthAndCulling();
7726 GL_AlphaTest(false);
7727 R_Mesh_ColorPointer(NULL, 0, 0);
7728 R_Mesh_ResetTextureState();
7729 R_SetupGenericShader(false);
7730 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7732 GL_BlendFunc(GL_ONE, GL_ZERO);
7733 GL_Color(0, 0, 0, 1);
7734 GL_DepthTest(writedepth);
7735 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7737 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7739 RSurf_SetupDepthAndCulling();
7740 GL_AlphaTest(false);
7741 R_Mesh_ColorPointer(NULL, 0, 0);
7742 R_Mesh_ResetTextureState();
7743 R_SetupGenericShader(false);
7744 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7746 GL_BlendFunc(GL_ONE, GL_ZERO);
7748 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7750 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7751 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7752 else if (!rsurface.texture->currentnumlayers)
7754 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7756 // transparent surfaces get pushed off into the transparent queue
7757 int surfacelistindex;
7758 const msurface_t *surface;
7759 vec3_t tempcenter, center;
7760 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7762 surface = texturesurfacelist[surfacelistindex];
7763 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7764 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7765 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7766 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7767 if (queueentity->transparent_offset) // transparent offset
7769 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
7770 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
7771 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
7773 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7778 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7779 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7784 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7788 // break the surface list down into batches by texture and use of lightmapping
7789 for (i = 0;i < numsurfaces;i = j)
7792 // texture is the base texture pointer, rsurface.texture is the
7793 // current frame/skin the texture is directing us to use (for example
7794 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7795 // use skin 1 instead)
7796 texture = surfacelist[i]->texture;
7797 rsurface.texture = R_GetCurrentTexture(texture);
7798 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7799 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7801 // if this texture is not the kind we want, skip ahead to the next one
7802 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7806 // simply scan ahead until we find a different texture or lightmap state
7807 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7809 // render the range of surfaces
7810 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7814 float locboxvertex3f[6*4*3] =
7816 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7817 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7818 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7819 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7820 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7821 1,0,0, 0,0,0, 0,1,0, 1,1,0
7824 unsigned short locboxelements[6*2*3] =
7834 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7837 cl_locnode_t *loc = (cl_locnode_t *)ent;
7839 float vertex3f[6*4*3];
7841 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7842 GL_DepthMask(false);
7843 GL_DepthRange(0, 1);
7844 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7846 GL_CullFace(GL_NONE);
7847 R_Mesh_Matrix(&identitymatrix);
7849 R_Mesh_VertexPointer(vertex3f, 0, 0);
7850 R_Mesh_ColorPointer(NULL, 0, 0);
7851 R_Mesh_ResetTextureState();
7852 R_SetupGenericShader(false);
7855 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7856 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7857 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7858 surfacelist[0] < 0 ? 0.5f : 0.125f);
7860 if (VectorCompare(loc->mins, loc->maxs))
7862 VectorSet(size, 2, 2, 2);
7863 VectorMA(loc->mins, -0.5f, size, mins);
7867 VectorCopy(loc->mins, mins);
7868 VectorSubtract(loc->maxs, loc->mins, size);
7871 for (i = 0;i < 6*4*3;)
7872 for (j = 0;j < 3;j++, i++)
7873 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7875 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7878 void R_DrawLocs(void)
7881 cl_locnode_t *loc, *nearestloc;
7883 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7884 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7886 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7887 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7891 void R_DrawDebugModel(entity_render_t *ent)
7893 int i, j, k, l, flagsmask;
7894 const int *elements;
7896 msurface_t *surface;
7897 dp_model_t *model = ent->model;
7900 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7902 R_Mesh_ColorPointer(NULL, 0, 0);
7903 R_Mesh_ResetTextureState();
7904 R_SetupGenericShader(false);
7905 GL_DepthRange(0, 1);
7906 GL_DepthTest(!r_showdisabledepthtest.integer);
7907 GL_DepthMask(false);
7908 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7910 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7912 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7913 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7915 if (brush->colbrushf && brush->colbrushf->numtriangles)
7917 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7918 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);
7919 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7922 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7924 if (surface->num_collisiontriangles)
7926 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7927 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);
7928 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7933 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7935 if (r_showtris.integer || r_shownormals.integer)
7937 if (r_showdisabledepthtest.integer)
7939 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7940 GL_DepthMask(false);
7944 GL_BlendFunc(GL_ONE, GL_ZERO);
7947 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7949 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7951 rsurface.texture = R_GetCurrentTexture(surface->texture);
7952 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7954 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7955 if (r_showtris.value > 0)
7957 if (!rsurface.texture->currentlayers->depthmask)
7958 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7959 else if (ent == r_refdef.scene.worldentity)
7960 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7962 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7963 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7964 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7965 R_Mesh_ColorPointer(NULL, 0, 0);
7966 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7967 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7968 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7969 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);
7970 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7973 if (r_shownormals.value < 0)
7976 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7978 VectorCopy(rsurface.vertex3f + l * 3, v);
7979 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7980 qglVertex3f(v[0], v[1], v[2]);
7981 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7982 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7983 qglVertex3f(v[0], v[1], v[2]);
7988 if (r_shownormals.value > 0)
7991 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7993 VectorCopy(rsurface.vertex3f + l * 3, v);
7994 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7995 qglVertex3f(v[0], v[1], v[2]);
7996 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7997 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7998 qglVertex3f(v[0], v[1], v[2]);
8003 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8005 VectorCopy(rsurface.vertex3f + l * 3, v);
8006 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8007 qglVertex3f(v[0], v[1], v[2]);
8008 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8009 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8010 qglVertex3f(v[0], v[1], v[2]);
8015 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8017 VectorCopy(rsurface.vertex3f + l * 3, v);
8018 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8019 qglVertex3f(v[0], v[1], v[2]);
8020 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8021 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8022 qglVertex3f(v[0], v[1], v[2]);
8029 rsurface.texture = NULL;
8033 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8034 int r_maxsurfacelist = 0;
8035 msurface_t **r_surfacelist = NULL;
8036 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8038 int i, j, endj, f, flagsmask;
8040 dp_model_t *model = r_refdef.scene.worldmodel;
8041 msurface_t *surfaces;
8042 unsigned char *update;
8043 int numsurfacelist = 0;
8047 if (r_maxsurfacelist < model->num_surfaces)
8049 r_maxsurfacelist = model->num_surfaces;
8051 Mem_Free(r_surfacelist);
8052 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8055 RSurf_ActiveWorldEntity();
8057 surfaces = model->data_surfaces;
8058 update = model->brushq1.lightmapupdateflags;
8060 // update light styles on this submodel
8061 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8063 model_brush_lightstyleinfo_t *style;
8064 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8066 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8068 int *list = style->surfacelist;
8069 style->value = r_refdef.scene.lightstylevalue[style->style];
8070 for (j = 0;j < style->numsurfaces;j++)
8071 update[list[j]] = true;
8076 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8080 R_DrawDebugModel(r_refdef.scene.worldentity);
8081 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8087 rsurface.uselightmaptexture = false;
8088 rsurface.texture = NULL;
8089 rsurface.rtlight = NULL;
8091 // add visible surfaces to draw list
8092 for (i = 0;i < model->nummodelsurfaces;i++)
8094 j = model->sortedmodelsurfaces[i];
8095 if (r_refdef.viewcache.world_surfacevisible[j])
8096 r_surfacelist[numsurfacelist++] = surfaces + j;
8098 // update lightmaps if needed
8100 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8101 if (r_refdef.viewcache.world_surfacevisible[j])
8103 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8104 // don't do anything if there were no surfaces
8105 if (!numsurfacelist)
8107 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8110 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8111 GL_AlphaTest(false);
8113 // add to stats if desired
8114 if (r_speeds.integer && !skysurfaces && !depthonly)
8116 r_refdef.stats.world_surfaces += numsurfacelist;
8117 for (j = 0;j < numsurfacelist;j++)
8118 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8120 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8123 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8125 int i, j, endj, f, flagsmask;
8127 dp_model_t *model = ent->model;
8128 msurface_t *surfaces;
8129 unsigned char *update;
8130 int numsurfacelist = 0;
8134 if (r_maxsurfacelist < model->num_surfaces)
8136 r_maxsurfacelist = model->num_surfaces;
8138 Mem_Free(r_surfacelist);
8139 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8142 // if the model is static it doesn't matter what value we give for
8143 // wantnormals and wanttangents, so this logic uses only rules applicable
8144 // to a model, knowing that they are meaningless otherwise
8145 if (ent == r_refdef.scene.worldentity)
8146 RSurf_ActiveWorldEntity();
8147 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8148 RSurf_ActiveModelEntity(ent, false, false);
8150 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8152 surfaces = model->data_surfaces;
8153 update = model->brushq1.lightmapupdateflags;
8155 // update light styles
8156 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8158 model_brush_lightstyleinfo_t *style;
8159 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8161 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8163 int *list = style->surfacelist;
8164 style->value = r_refdef.scene.lightstylevalue[style->style];
8165 for (j = 0;j < style->numsurfaces;j++)
8166 update[list[j]] = true;
8171 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8175 R_DrawDebugModel(ent);
8176 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8182 rsurface.uselightmaptexture = false;
8183 rsurface.texture = NULL;
8184 rsurface.rtlight = NULL;
8186 // add visible surfaces to draw list
8187 for (i = 0;i < model->nummodelsurfaces;i++)
8188 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8189 // don't do anything if there were no surfaces
8190 if (!numsurfacelist)
8192 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8195 // update lightmaps if needed
8197 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8199 R_BuildLightMap(ent, surfaces + j);
8200 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8201 GL_AlphaTest(false);
8203 // add to stats if desired
8204 if (r_speeds.integer && !skysurfaces && !depthonly)
8206 r_refdef.stats.entities_surfaces += numsurfacelist;
8207 for (j = 0;j < numsurfacelist;j++)
8208 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8210 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity