2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
47 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
48 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
49 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "1", "light equalizing: ensure at least this ambient/diffuse ratio"};
50 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
51 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
53 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
55 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
56 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
57 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
58 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
59 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
60 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
61 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
62 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
63 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
64 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
65 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
66 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
67 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
68 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
69 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
70 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
71 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
72 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
73 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
74 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
75 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
76 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
77 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
78 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
79 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
80 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
81 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
82 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
83 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
84 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
85 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
86 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
87 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
88 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "4", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
89 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
90 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
92 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
93 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
94 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
95 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
96 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
97 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
98 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
99 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
101 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
103 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
104 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
105 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
106 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
107 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
108 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
109 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
110 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
111 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
112 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
113 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
115 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
116 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
117 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
118 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
119 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
121 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
122 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
123 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
124 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
126 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
127 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
128 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
129 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
130 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
131 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
132 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
134 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
135 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
136 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
137 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
139 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
141 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
143 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
145 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
146 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
147 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
148 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
149 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
150 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
151 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
153 extern cvar_t v_glslgamma;
155 extern qboolean v_flipped_state;
157 static struct r_bloomstate_s
162 int bloomwidth, bloomheight;
164 int screentexturewidth, screentextureheight;
165 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
167 int bloomtexturewidth, bloomtextureheight;
168 rtexture_t *texture_bloom;
170 // arrays for rendering the screen passes
171 float screentexcoord2f[8];
172 float bloomtexcoord2f[8];
173 float offsettexcoord2f[8];
175 r_viewport_t viewport;
179 r_waterstate_t r_waterstate;
181 /// shadow volume bsp struct with automatically growing nodes buffer
184 rtexture_t *r_texture_blanknormalmap;
185 rtexture_t *r_texture_white;
186 rtexture_t *r_texture_grey128;
187 rtexture_t *r_texture_black;
188 rtexture_t *r_texture_notexture;
189 rtexture_t *r_texture_whitecube;
190 rtexture_t *r_texture_normalizationcube;
191 rtexture_t *r_texture_fogattenuation;
192 rtexture_t *r_texture_gammaramps;
193 unsigned int r_texture_gammaramps_serial;
194 //rtexture_t *r_texture_fogintensity;
196 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
197 unsigned int r_numqueries;
198 unsigned int r_maxqueries;
200 typedef struct r_qwskincache_s
202 char name[MAX_QPATH];
203 skinframe_t *skinframe;
207 static r_qwskincache_t *r_qwskincache;
208 static int r_qwskincache_size;
210 /// vertex coordinates for a quad that covers the screen exactly
211 const float r_screenvertex3f[12] =
219 extern void R_DrawModelShadows(void);
221 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
224 for (i = 0;i < verts;i++)
235 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
238 for (i = 0;i < verts;i++)
248 // FIXME: move this to client?
251 if (gamemode == GAME_NEHAHRA)
253 Cvar_Set("gl_fogenable", "0");
254 Cvar_Set("gl_fogdensity", "0.2");
255 Cvar_Set("gl_fogred", "0.3");
256 Cvar_Set("gl_foggreen", "0.3");
257 Cvar_Set("gl_fogblue", "0.3");
259 r_refdef.fog_density = 0;
260 r_refdef.fog_red = 0;
261 r_refdef.fog_green = 0;
262 r_refdef.fog_blue = 0;
263 r_refdef.fog_alpha = 1;
264 r_refdef.fog_start = 0;
265 r_refdef.fog_end = 0;
268 static void R_BuildBlankTextures(void)
270 unsigned char data[4];
271 data[2] = 128; // normal X
272 data[1] = 128; // normal Y
273 data[0] = 255; // normal Z
274 data[3] = 128; // height
275 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
280 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
285 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
290 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
293 static void R_BuildNoTexture(void)
296 unsigned char pix[16][16][4];
297 // this makes a light grey/dark grey checkerboard texture
298 for (y = 0;y < 16;y++)
300 for (x = 0;x < 16;x++)
302 if ((y < 8) ^ (x < 8))
318 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
321 static void R_BuildWhiteCube(void)
323 unsigned char data[6*1*1*4];
324 memset(data, 255, sizeof(data));
325 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
328 static void R_BuildNormalizationCube(void)
332 vec_t s, t, intensity;
334 unsigned char data[6][NORMSIZE][NORMSIZE][4];
335 for (side = 0;side < 6;side++)
337 for (y = 0;y < NORMSIZE;y++)
339 for (x = 0;x < NORMSIZE;x++)
341 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
342 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
377 intensity = 127.0f / sqrt(DotProduct(v, v));
378 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
379 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
380 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
381 data[side][y][x][3] = 255;
385 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
388 static void R_BuildFogTexture(void)
392 unsigned char data1[FOGWIDTH][4];
393 //unsigned char data2[FOGWIDTH][4];
396 r_refdef.fogmasktable_start = r_refdef.fog_start;
397 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
398 r_refdef.fogmasktable_range = r_refdef.fogrange;
399 r_refdef.fogmasktable_density = r_refdef.fog_density;
401 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
402 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
404 d = (x * r - r_refdef.fogmasktable_start);
405 if(developer.integer >= 100)
406 Con_Printf("%f ", d);
408 if (r_fog_exp2.integer)
409 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
411 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
412 if(developer.integer >= 100)
413 Con_Printf(" : %f ", alpha);
414 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
415 if(developer.integer >= 100)
416 Con_Printf(" = %f\n", alpha);
417 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
420 for (x = 0;x < FOGWIDTH;x++)
422 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
427 //data2[x][0] = 255 - b;
428 //data2[x][1] = 255 - b;
429 //data2[x][2] = 255 - b;
432 if (r_texture_fogattenuation)
434 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
435 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
439 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
440 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
444 static const char *builtinshaderstring =
445 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
446 "// written by Forest 'LordHavoc' Hale\n"
448 "// enable various extensions depending on permutation:\n"
450 "#ifdef USESHADOWMAPRECT\n"
451 "# extension GL_ARB_texture_rectangle : enable\n"
454 "#ifdef USESHADOWMAP2D\n"
455 "# ifdef GL_EXT_gpu_shader4\n"
456 "# extension GL_EXT_gpu_shader4 : enable\n"
458 "# ifdef GL_ARB_texture_gather\n"
459 "# extension GL_ARB_texture_gather : enable\n"
461 "# ifdef GL_AMD_texture_texture4\n"
462 "# extension GL_AMD_texture_texture4 : enable\n"
467 "#ifdef USESHADOWMAPCUBE\n"
468 "# extension GL_EXT_gpu_shader4 : enable\n"
471 "#ifdef USESHADOWSAMPLER\n"
472 "# extension GL_ARB_shadow : enable\n"
475 "// common definitions between vertex shader and fragment shader:\n"
477 "//#ifdef __GLSL_CG_DATA_TYPES\n"
478 "//# define myhalf half\n"
479 "//# define myhalf2 half2\n"
480 "//# define myhalf3half3\n"
481 "//# define myhalf4 half4\n"
483 "# define myhalf float\n"
484 "# define myhalf2 vec2\n"
485 "# define myhalf3 vec3\n"
486 "# define myhalf4 vec4\n"
489 "#ifdef MODE_DEPTH_OR_SHADOW\n"
491 "# ifdef VERTEX_SHADER\n"
494 " gl_Position = ftransform();\n"
499 "#ifdef MODE_SHOWDEPTH\n"
500 "# ifdef VERTEX_SHADER\n"
503 " gl_Position = ftransform();\n"
504 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
507 "# ifdef FRAGMENT_SHADER\n"
510 " gl_FragColor = gl_Color;\n"
514 "#else // !MODE_SHOWDEPTH\n"
516 "#ifdef MODE_POSTPROCESS\n"
517 "# ifdef VERTEX_SHADER\n"
520 " gl_FrontColor = gl_Color;\n"
521 " gl_Position = ftransform();\n"
522 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
524 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
528 "# ifdef FRAGMENT_SHADER\n"
530 "uniform sampler2D Texture_First;\n"
532 "uniform sampler2D Texture_Second;\n"
534 "#ifdef USEGAMMARAMPS\n"
535 "uniform sampler2D Texture_GammaRamps;\n"
537 "#ifdef USESATURATION\n"
538 "uniform float Saturation;\n"
540 "#ifdef USEVIEWTINT\n"
541 "uniform vec4 TintColor;\n"
543 "//uncomment these if you want to use them:\n"
544 "uniform vec4 UserVec1;\n"
545 "// uniform vec4 UserVec2;\n"
546 "// uniform vec4 UserVec3;\n"
547 "// uniform vec4 UserVec4;\n"
548 "// uniform float ClientTime;\n"
549 "uniform vec2 PixelSize;\n"
552 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
554 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
556 "#ifdef USEVIEWTINT\n"
557 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
560 "#ifdef USEPOSTPROCESSING\n"
561 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
562 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
563 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
564 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
565 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
566 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
567 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
568 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
571 "#ifdef USESATURATION\n"
572 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
573 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
574 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
575 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
578 "#ifdef USEGAMMARAMPS\n"
579 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
580 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
581 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
588 "#ifdef MODE_GENERIC\n"
589 "# ifdef VERTEX_SHADER\n"
592 " gl_FrontColor = gl_Color;\n"
593 "# ifdef USEDIFFUSE\n"
594 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
596 "# ifdef USESPECULAR\n"
597 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
599 " gl_Position = ftransform();\n"
602 "# ifdef FRAGMENT_SHADER\n"
604 "# ifdef USEDIFFUSE\n"
605 "uniform sampler2D Texture_First;\n"
607 "# ifdef USESPECULAR\n"
608 "uniform sampler2D Texture_Second;\n"
613 " gl_FragColor = gl_Color;\n"
614 "# ifdef USEDIFFUSE\n"
615 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
618 "# ifdef USESPECULAR\n"
619 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
621 "# ifdef USECOLORMAPPING\n"
622 " gl_FragColor *= tex2;\n"
625 " gl_FragColor += tex2;\n"
627 "# ifdef USEVERTEXTEXTUREBLEND\n"
628 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
633 "#else // !MODE_GENERIC\n"
635 "varying vec2 TexCoord;\n"
636 "#ifdef USEVERTEXTEXTUREBLEND\n"
637 "varying vec2 TexCoord2;\n"
639 "varying vec2 TexCoordLightmap;\n"
641 "#ifdef MODE_LIGHTSOURCE\n"
642 "varying vec3 CubeVector;\n"
645 "#ifdef MODE_LIGHTSOURCE\n"
646 "varying vec3 LightVector;\n"
648 "#ifdef MODE_LIGHTDIRECTION\n"
649 "varying vec3 LightVector;\n"
652 "varying vec3 EyeVector;\n"
654 "varying vec3 EyeVectorModelSpace;\n"
657 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
658 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
659 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
661 "#ifdef MODE_WATER\n"
662 "varying vec4 ModelViewProjectionPosition;\n"
664 "#ifdef MODE_REFRACTION\n"
665 "varying vec4 ModelViewProjectionPosition;\n"
667 "#ifdef USEREFLECTION\n"
668 "varying vec4 ModelViewProjectionPosition;\n"
675 "// vertex shader specific:\n"
676 "#ifdef VERTEX_SHADER\n"
678 "uniform vec3 LightPosition;\n"
679 "uniform vec3 EyePosition;\n"
680 "uniform vec3 LightDir;\n"
682 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
686 " gl_FrontColor = gl_Color;\n"
687 " // copy the surface texcoord\n"
688 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
689 "#ifdef USEVERTEXTEXTUREBLEND\n"
690 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
692 "#ifndef MODE_LIGHTSOURCE\n"
693 "# ifndef MODE_LIGHTDIRECTION\n"
694 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
698 "#ifdef MODE_LIGHTSOURCE\n"
699 " // transform vertex position into light attenuation/cubemap space\n"
700 " // (-1 to +1 across the light box)\n"
701 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
703 " // transform unnormalized light direction into tangent space\n"
704 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
705 " // normalize it per pixel)\n"
706 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
707 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
708 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
709 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
712 "#ifdef MODE_LIGHTDIRECTION\n"
713 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
714 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
715 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
718 " // transform unnormalized eye direction into tangent space\n"
720 " vec3 EyeVectorModelSpace;\n"
722 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
723 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
724 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
725 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
727 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
728 " VectorS = gl_MultiTexCoord1.xyz;\n"
729 " VectorT = gl_MultiTexCoord2.xyz;\n"
730 " VectorR = gl_MultiTexCoord3.xyz;\n"
733 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
734 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
735 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
736 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
739 "// transform vertex to camera space, using ftransform to match non-VS\n"
741 " gl_Position = ftransform();\n"
743 "#ifdef MODE_WATER\n"
744 " ModelViewProjectionPosition = gl_Position;\n"
746 "#ifdef MODE_REFRACTION\n"
747 " ModelViewProjectionPosition = gl_Position;\n"
749 "#ifdef USEREFLECTION\n"
750 " ModelViewProjectionPosition = gl_Position;\n"
754 "#endif // VERTEX_SHADER\n"
759 "// fragment shader specific:\n"
760 "#ifdef FRAGMENT_SHADER\n"
762 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
763 "uniform sampler2D Texture_Normal;\n"
764 "uniform sampler2D Texture_Color;\n"
765 "uniform sampler2D Texture_Gloss;\n"
766 "uniform sampler2D Texture_Glow;\n"
767 "uniform sampler2D Texture_SecondaryNormal;\n"
768 "uniform sampler2D Texture_SecondaryColor;\n"
769 "uniform sampler2D Texture_SecondaryGloss;\n"
770 "uniform sampler2D Texture_SecondaryGlow;\n"
771 "uniform sampler2D Texture_Pants;\n"
772 "uniform sampler2D Texture_Shirt;\n"
773 "uniform sampler2D Texture_FogMask;\n"
774 "uniform sampler2D Texture_Lightmap;\n"
775 "uniform sampler2D Texture_Deluxemap;\n"
776 "uniform sampler2D Texture_Refraction;\n"
777 "uniform sampler2D Texture_Reflection;\n"
778 "uniform sampler2D Texture_Attenuation;\n"
779 "uniform samplerCube Texture_Cube;\n"
781 "#define showshadowmap 0\n"
783 "#ifdef USESHADOWMAPRECT\n"
784 "# ifdef USESHADOWSAMPLER\n"
785 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
787 "uniform sampler2DRect Texture_ShadowMapRect;\n"
791 "#ifdef USESHADOWMAP2D\n"
792 "# ifdef USESHADOWSAMPLER\n"
793 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
795 "uniform sampler2D Texture_ShadowMap2D;\n"
799 "#ifdef USESHADOWMAPVSDCT\n"
800 "uniform samplerCube Texture_CubeProjection;\n"
803 "#ifdef USESHADOWMAPCUBE\n"
804 "# ifdef USESHADOWSAMPLER\n"
805 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
807 "uniform samplerCube Texture_ShadowMapCube;\n"
811 "uniform myhalf3 LightColor;\n"
812 "uniform myhalf3 AmbientColor;\n"
813 "uniform myhalf3 DiffuseColor;\n"
814 "uniform myhalf3 SpecularColor;\n"
815 "uniform myhalf3 Color_Pants;\n"
816 "uniform myhalf3 Color_Shirt;\n"
817 "uniform myhalf3 FogColor;\n"
819 "uniform myhalf4 TintColor;\n"
822 "//#ifdef MODE_WATER\n"
823 "uniform vec4 DistortScaleRefractReflect;\n"
824 "uniform vec4 ScreenScaleRefractReflect;\n"
825 "uniform vec4 ScreenCenterRefractReflect;\n"
826 "uniform myhalf4 RefractColor;\n"
827 "uniform myhalf4 ReflectColor;\n"
828 "uniform myhalf ReflectFactor;\n"
829 "uniform myhalf ReflectOffset;\n"
831 "//# ifdef MODE_REFRACTION\n"
832 "//uniform vec4 DistortScaleRefractReflect;\n"
833 "//uniform vec4 ScreenScaleRefractReflect;\n"
834 "//uniform vec4 ScreenCenterRefractReflect;\n"
835 "//uniform myhalf4 RefractColor;\n"
836 "//# ifdef USEREFLECTION\n"
837 "//uniform myhalf4 ReflectColor;\n"
840 "//# ifdef USEREFLECTION\n"
841 "//uniform vec4 DistortScaleRefractReflect;\n"
842 "//uniform vec4 ScreenScaleRefractReflect;\n"
843 "//uniform vec4 ScreenCenterRefractReflect;\n"
844 "//uniform myhalf4 ReflectColor;\n"
849 "uniform myhalf3 GlowColor;\n"
850 "uniform myhalf SceneBrightness;\n"
852 "uniform float OffsetMapping_Scale;\n"
853 "uniform float OffsetMapping_Bias;\n"
854 "uniform float FogRangeRecip;\n"
856 "uniform myhalf AmbientScale;\n"
857 "uniform myhalf DiffuseScale;\n"
858 "uniform myhalf SpecularScale;\n"
859 "uniform myhalf SpecularPower;\n"
861 "#ifdef USEOFFSETMAPPING\n"
862 "vec2 OffsetMapping(vec2 TexCoord)\n"
864 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
865 " // 14 sample relief mapping: linear search and then binary search\n"
866 " // this basically steps forward a small amount repeatedly until it finds\n"
867 " // itself inside solid, then jitters forward and back using decreasing\n"
868 " // amounts to find the impact\n"
869 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
870 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
871 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
872 " vec3 RT = vec3(TexCoord, 1);\n"
873 " OffsetVector *= 0.1;\n"
874 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
875 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
876 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
877 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
878 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
879 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
880 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
881 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
882 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
883 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
884 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
885 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
886 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
887 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
890 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
891 " // this basically moves forward the full distance, and then backs up based\n"
892 " // on height of samples\n"
893 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
894 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
895 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
896 " TexCoord += OffsetVector;\n"
897 " OffsetVector *= 0.333;\n"
898 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
899 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
900 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
901 " return TexCoord;\n"
904 "#endif // USEOFFSETMAPPING\n"
906 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
907 "uniform vec2 ShadowMap_TextureScale;\n"
908 "uniform vec4 ShadowMap_Parameters;\n"
911 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
912 "vec3 GetShadowMapTC2D(vec3 dir)\n"
914 " vec3 adir = abs(dir);\n"
915 "# ifndef USESHADOWMAPVSDCT\n"
919 " if (adir.x > adir.y)\n"
921 " if (adir.x > adir.z) // X\n"
925 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
931 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
936 " if (adir.y > adir.z) // Y\n"
940 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
946 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
950 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
951 " stc.xy += offset * ShadowMap_Parameters.y;\n"
952 " stc.z += ShadowMap_Parameters.z;\n"
953 "# if showshadowmap\n"
954 " stc.xy *= ShadowMap_TextureScale;\n"
958 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
959 " float ma = max(max(adir.x, adir.y), adir.z);\n"
960 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
961 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
962 " stc.z += ShadowMap_Parameters.z;\n"
963 "# if showshadowmap\n"
964 " stc.xy *= ShadowMap_TextureScale;\n"
969 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
971 "#ifdef USESHADOWMAPCUBE\n"
972 "vec4 GetShadowMapTCCube(vec3 dir)\n"
974 " vec3 adir = abs(dir);\n"
975 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
979 "#if !showshadowmap\n"
980 "# ifdef USESHADOWMAPRECT\n"
981 "float ShadowMapCompare(vec3 dir)\n"
983 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
985 "# ifdef USESHADOWSAMPLER\n"
987 "# ifdef USESHADOWMAPPCF\n"
988 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
989 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
991 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
996 "# ifdef USESHADOWMAPPCF\n"
997 "# if USESHADOWMAPPCF > 1\n"
998 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
999 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1000 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1001 " vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
1002 " vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
1003 " vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
1004 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1005 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1007 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1008 " vec2 offset = fract(shadowmaptc.xy);\n"
1009 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1010 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1011 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1012 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1013 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1016 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1024 "# ifdef USESHADOWMAP2D\n"
1025 "float ShadowMapCompare(vec3 dir)\n"
1027 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1030 "# ifdef USESHADOWSAMPLER\n"
1031 "# ifdef USESHADOWMAPPCF\n"
1032 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1033 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1034 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1036 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1039 "# ifdef USESHADOWMAPPCF\n"
1040 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1041 "# ifdef GL_ARB_texture_gather\n"
1042 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1044 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1046 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1047 " center *= ShadowMap_TextureScale;\n"
1048 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1049 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1050 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1051 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1052 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1053 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1054 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1056 "# ifdef GL_EXT_gpu_shader4\n"
1057 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1059 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1061 "# if USESHADOWMAPPCF > 1\n"
1062 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1063 " center *= ShadowMap_TextureScale;\n"
1064 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1065 " vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
1066 " vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
1067 " vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
1068 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1069 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1071 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1072 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1073 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1074 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1075 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1076 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1080 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1087 "# ifdef USESHADOWMAPCUBE\n"
1088 "float ShadowMapCompare(vec3 dir)\n"
1090 " // apply depth texture cubemap as light filter\n"
1091 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1093 "# ifdef USESHADOWSAMPLER\n"
1094 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1096 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1103 "#ifdef MODE_WATER\n"
1108 "#ifdef USEOFFSETMAPPING\n"
1109 " // apply offsetmapping\n"
1110 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1111 "#define TexCoord TexCoordOffset\n"
1114 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1115 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1116 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1117 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1118 " // FIXME temporary hack to detect the case that the reflection\n"
1119 " // gets blackened at edges due to leaving the area that contains actual\n"
1121 " // Remove this 'ack once we have a better way to stop this thing from\n"
1123 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1124 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1125 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1126 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1127 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1128 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1129 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1130 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1131 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1132 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1133 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1134 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1137 "#else // !MODE_WATER\n"
1138 "#ifdef MODE_REFRACTION\n"
1140 "// refraction pass\n"
1143 "#ifdef USEOFFSETMAPPING\n"
1144 " // apply offsetmapping\n"
1145 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1146 "#define TexCoord TexCoordOffset\n"
1149 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1150 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1151 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1152 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1153 " // FIXME temporary hack to detect the case that the reflection\n"
1154 " // gets blackened at edges due to leaving the area that contains actual\n"
1156 " // Remove this 'ack once we have a better way to stop this thing from\n"
1158 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1159 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1160 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1161 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1162 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1163 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1166 "#else // !MODE_REFRACTION\n"
1169 "#ifdef USEOFFSETMAPPING\n"
1170 " // apply offsetmapping\n"
1171 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1172 "#define TexCoord TexCoordOffset\n"
1175 " // combine the diffuse textures (base, pants, shirt)\n"
1176 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1177 "#ifdef USECOLORMAPPING\n"
1178 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1180 "#ifdef USEVERTEXTEXTUREBLEND\n"
1181 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1182 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1183 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1184 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1186 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1189 "#ifdef USEDIFFUSE\n"
1190 " // get the surface normal and the gloss color\n"
1191 "# ifdef USEVERTEXTEXTUREBLEND\n"
1192 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1193 "# ifdef USESPECULAR\n"
1194 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1197 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1198 "# ifdef USESPECULAR\n"
1199 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1206 "#ifdef MODE_LIGHTSOURCE\n"
1207 " // light source\n"
1209 " // calculate surface normal, light normal, and specular normal\n"
1210 " // compute color intensity for the two textures (colormap and glossmap)\n"
1211 " // scale by light color and attenuation as efficiently as possible\n"
1212 " // (do as much scalar math as possible rather than vector math)\n"
1213 "# ifdef USEDIFFUSE\n"
1214 " // get the light normal\n"
1215 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1217 "# ifdef USESPECULAR\n"
1218 "# ifndef USEEXACTSPECULARMATH\n"
1219 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1222 " // calculate directional shading\n"
1223 "# ifdef USEEXACTSPECULARMATH\n"
1224 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
1226 " color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n"
1229 "# ifdef USEDIFFUSE\n"
1230 " // calculate directional shading\n"
1231 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1233 " // calculate directionless shading\n"
1234 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1238 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1239 "#if !showshadowmap\n"
1240 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1244 "# ifdef USECUBEFILTER\n"
1245 " // apply light cubemap filter\n"
1246 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1247 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1249 "#endif // MODE_LIGHTSOURCE\n"
1254 "#ifdef MODE_LIGHTDIRECTION\n"
1255 " // directional model lighting\n"
1256 "# ifdef USEDIFFUSE\n"
1257 " // get the light normal\n"
1258 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1260 "# ifdef USESPECULAR\n"
1261 " // calculate directional shading\n"
1262 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1263 "# ifdef USEEXACTSPECULARMATH\n"
1264 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1266 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1267 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1270 "# ifdef USEDIFFUSE\n"
1272 " // calculate directional shading\n"
1273 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1275 " color.rgb *= AmbientColor;\n"
1278 "#endif // MODE_LIGHTDIRECTION\n"
1283 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1284 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1286 " // get the light normal\n"
1287 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1288 " myhalf3 diffusenormal;\n"
1289 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1290 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1291 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1292 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1293 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1294 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1295 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1296 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1297 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1298 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1299 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1300 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1301 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1302 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1303 "# ifdef USESPECULAR\n"
1304 "# ifdef USEEXACTSPECULARMATH\n"
1305 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1307 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1308 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1312 " // apply lightmap color\n"
1313 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1314 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1319 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1320 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1322 " // get the light normal\n"
1323 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1324 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1325 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1326 "# ifdef USESPECULAR\n"
1327 "# ifdef USEEXACTSPECULARMATH\n"
1328 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1330 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1331 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1335 " // apply lightmap color\n"
1336 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1337 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1342 "#ifdef MODE_LIGHTMAP\n"
1343 " // apply lightmap color\n"
1344 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1345 "#endif // MODE_LIGHTMAP\n"
1350 "#ifdef MODE_VERTEXCOLOR\n"
1351 " // apply lightmap color\n"
1352 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1353 "#endif // MODE_VERTEXCOLOR\n"
1358 "#ifdef MODE_FLATCOLOR\n"
1359 "#endif // MODE_FLATCOLOR\n"
1367 " color *= TintColor;\n"
1370 "#ifdef USEVERTEXTEXTUREBLEND\n"
1371 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1373 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1377 " color.rgb *= SceneBrightness;\n"
1379 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1381 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1384 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1385 "#ifdef USEREFLECTION\n"
1386 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1387 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1388 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1389 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1390 " // FIXME temporary hack to detect the case that the reflection\n"
1391 " // gets blackened at edges due to leaving the area that contains actual\n"
1393 " // Remove this 'ack once we have a better way to stop this thing from\n"
1395 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1396 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1397 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1398 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1399 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1400 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1403 " gl_FragColor = vec4(color);\n"
1405 "#if showshadowmap\n"
1406 "# ifdef USESHADOWMAPRECT\n"
1407 "# ifdef USESHADOWSAMPLER\n"
1408 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1410 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1413 "# ifdef USESHADOWMAP2D\n"
1414 "# ifdef USESHADOWSAMPLER\n"
1415 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1417 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1421 "# ifdef USESHADOWMAPCUBE\n"
1422 "# ifdef USESHADOWSAMPLER\n"
1423 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1425 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1430 "#endif // !MODE_REFRACTION\n"
1431 "#endif // !MODE_WATER\n"
1433 "#endif // FRAGMENT_SHADER\n"
1435 "#endif // !MODE_GENERIC\n"
1436 "#endif // !MODE_POSTPROCESS\n"
1437 "#endif // !MODE_SHOWDEPTH\n"
1438 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1441 typedef struct shaderpermutationinfo_s
1443 const char *pretext;
1446 shaderpermutationinfo_t;
1448 typedef struct shadermodeinfo_s
1450 const char *vertexfilename;
1451 const char *geometryfilename;
1452 const char *fragmentfilename;
1453 const char *pretext;
1458 typedef enum shaderpermutation_e
1460 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1461 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1462 SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
1463 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1464 SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
1465 SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
1466 SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
1467 SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
1468 SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
1469 SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
1470 SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
1471 SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
1472 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1473 SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1474 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
1475 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1476 SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
1477 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
1478 SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
1479 SHADERPERMUTATION_SHADOWMAPPCF = 1<<14, ///< (lightsource) use percentage closer filtering on shadowmap test results
1480 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<15, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1481 SHADERPERMUTATION_SHADOWSAMPLER = 1<<16, ///< (lightsource) use hardware shadowmap test
1482 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<17, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1483 SHADERPERMUTATION_LIMIT = 1<<18, ///< size of permutations array
1484 SHADERPERMUTATION_COUNT = 18 ///< size of shaderpermutationinfo array
1486 shaderpermutation_t;
1488 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1489 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1491 {"#define USEDIFFUSE\n", " diffuse"},
1492 {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
1493 {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
1494 {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
1495 {"#define USECUBEFILTER\n", " cubefilter"},
1496 {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
1497 {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
1498 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1499 {"#define USEREFLECTION\n", " reflection"},
1500 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1501 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1502 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1503 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1504 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1505 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1506 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1507 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1508 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1511 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1512 typedef enum shadermode_e
1514 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1515 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1516 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1517 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1518 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1519 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1520 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1521 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1522 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1523 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1524 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1525 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1526 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1531 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1532 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1534 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1535 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1536 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1537 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1538 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1539 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1540 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1541 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1542 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1543 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1544 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1545 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1546 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1549 struct r_glsl_permutation_s;
1550 typedef struct r_glsl_permutation_s
1552 /// hash lookup data
1553 struct r_glsl_permutation_s *hashnext;
1555 unsigned int permutation;
1557 /// indicates if we have tried compiling this permutation already
1559 /// 0 if compilation failed
1561 /// locations of detected uniforms in program object, or -1 if not found
1562 int loc_Texture_First;
1563 int loc_Texture_Second;
1564 int loc_Texture_GammaRamps;
1565 int loc_Texture_Normal;
1566 int loc_Texture_Color;
1567 int loc_Texture_Gloss;
1568 int loc_Texture_Glow;
1569 int loc_Texture_SecondaryNormal;
1570 int loc_Texture_SecondaryColor;
1571 int loc_Texture_SecondaryGloss;
1572 int loc_Texture_SecondaryGlow;
1573 int loc_Texture_Pants;
1574 int loc_Texture_Shirt;
1575 int loc_Texture_FogMask;
1576 int loc_Texture_Lightmap;
1577 int loc_Texture_Deluxemap;
1578 int loc_Texture_Attenuation;
1579 int loc_Texture_Cube;
1580 int loc_Texture_Refraction;
1581 int loc_Texture_Reflection;
1582 int loc_Texture_ShadowMapRect;
1583 int loc_Texture_ShadowMapCube;
1584 int loc_Texture_ShadowMap2D;
1585 int loc_Texture_CubeProjection;
1587 int loc_LightPosition;
1588 int loc_EyePosition;
1589 int loc_Color_Pants;
1590 int loc_Color_Shirt;
1591 int loc_FogRangeRecip;
1592 int loc_AmbientScale;
1593 int loc_DiffuseScale;
1594 int loc_SpecularScale;
1595 int loc_SpecularPower;
1597 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1598 int loc_OffsetMapping_Scale;
1600 int loc_AmbientColor;
1601 int loc_DiffuseColor;
1602 int loc_SpecularColor;
1604 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1605 int loc_GammaCoeff; ///< 1 / gamma
1606 int loc_DistortScaleRefractReflect;
1607 int loc_ScreenScaleRefractReflect;
1608 int loc_ScreenCenterRefractReflect;
1609 int loc_RefractColor;
1610 int loc_ReflectColor;
1611 int loc_ReflectFactor;
1612 int loc_ReflectOffset;
1620 int loc_ShadowMap_TextureScale;
1621 int loc_ShadowMap_Parameters;
1623 r_glsl_permutation_t;
1625 #define SHADERPERMUTATION_HASHSIZE 4096
1627 /// information about each possible shader permutation
1628 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1629 /// currently selected permutation
1630 r_glsl_permutation_t *r_glsl_permutation;
1631 /// storage for permutations linked in the hash table
1632 memexpandablearray_t r_glsl_permutationarray;
1634 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1636 //unsigned int hashdepth = 0;
1637 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1638 r_glsl_permutation_t *p;
1639 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1641 if (p->mode == mode && p->permutation == permutation)
1643 //if (hashdepth > 10)
1644 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1649 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1651 p->permutation = permutation;
1652 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1653 r_glsl_permutationhash[mode][hashindex] = p;
1654 //if (hashdepth > 10)
1655 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1659 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1662 if (!filename || !filename[0])
1664 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1667 if (printfromdisknotice)
1668 Con_DPrint("from disk... ");
1669 return shaderstring;
1671 else if (!strcmp(filename, "glsl/default.glsl"))
1673 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1674 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1676 return shaderstring;
1679 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1682 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1683 int vertstrings_count = 0;
1684 int geomstrings_count = 0;
1685 int fragstrings_count = 0;
1686 char *vertexstring, *geometrystring, *fragmentstring;
1687 const char *vertstrings_list[32+3];
1688 const char *geomstrings_list[32+3];
1689 const char *fragstrings_list[32+3];
1690 char permutationname[256];
1697 permutationname[0] = 0;
1698 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1699 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1700 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1702 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1704 // the first pretext is which type of shader to compile as
1705 // (later these will all be bound together as a program object)
1706 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1707 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1708 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1710 // the second pretext is the mode (for example a light source)
1711 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1712 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1713 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1714 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1716 // now add all the permutation pretexts
1717 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1719 if (permutation & (1<<i))
1721 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1722 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1723 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1724 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1728 // keep line numbers correct
1729 vertstrings_list[vertstrings_count++] = "\n";
1730 geomstrings_list[geomstrings_count++] = "\n";
1731 fragstrings_list[fragstrings_count++] = "\n";
1735 // now append the shader text itself
1736 vertstrings_list[vertstrings_count++] = vertexstring;
1737 geomstrings_list[geomstrings_count++] = geometrystring;
1738 fragstrings_list[fragstrings_count++] = fragmentstring;
1740 // if any sources were NULL, clear the respective list
1742 vertstrings_count = 0;
1743 if (!geometrystring)
1744 geomstrings_count = 0;
1745 if (!fragmentstring)
1746 fragstrings_count = 0;
1748 // compile the shader program
1749 if (vertstrings_count + geomstrings_count + fragstrings_count)
1750 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1754 qglUseProgramObjectARB(p->program);CHECKGLERROR
1755 // look up all the uniform variable names we care about, so we don't
1756 // have to look them up every time we set them
1757 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1758 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1759 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1760 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1761 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1762 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1763 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1764 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1765 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1766 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1767 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1768 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1769 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1770 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1771 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1772 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1773 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1774 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1775 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1776 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1777 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1778 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1779 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1780 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1781 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1782 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1783 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1784 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1785 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1786 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1787 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1788 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1789 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1790 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1791 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1792 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1793 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1794 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1795 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1796 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1797 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1798 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1799 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1800 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1801 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1802 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1803 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1804 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1805 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1806 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1807 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1808 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1809 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1810 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1811 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1812 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1813 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1814 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1815 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1816 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1817 // initialize the samplers to refer to the texture units we use
1818 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1819 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1820 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1821 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1822 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1823 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1824 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1825 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1826 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1827 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1828 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1829 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1830 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1831 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1832 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1833 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1834 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1835 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1836 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1837 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1838 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1839 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1840 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1841 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1843 if (developer.integer)
1844 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1847 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1851 Mem_Free(vertexstring);
1853 Mem_Free(geometrystring);
1855 Mem_Free(fragmentstring);
1858 void R_GLSL_Restart_f(void)
1860 unsigned int i, limit;
1861 r_glsl_permutation_t *p;
1862 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1863 for (i = 0;i < limit;i++)
1865 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1867 GL_Backend_FreeProgram(p->program);
1868 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1871 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1874 void R_GLSL_DumpShader_f(void)
1878 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1881 Con_Printf("failed to write to glsl/default.glsl\n");
1885 FS_Print(file, "/* The engine may define the following macros:\n");
1886 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1887 for (i = 0;i < SHADERMODE_COUNT;i++)
1888 FS_Print(file, shadermodeinfo[i].pretext);
1889 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1890 FS_Print(file, shaderpermutationinfo[i].pretext);
1891 FS_Print(file, "*/\n");
1892 FS_Print(file, builtinshaderstring);
1895 Con_Printf("glsl/default.glsl written\n");
1898 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1900 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1901 if (r_glsl_permutation != perm)
1903 r_glsl_permutation = perm;
1904 if (!r_glsl_permutation->program)
1906 if (!r_glsl_permutation->compiled)
1907 R_GLSL_CompilePermutation(perm, mode, permutation);
1908 if (!r_glsl_permutation->program)
1910 // remove features until we find a valid permutation
1912 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1914 // reduce i more quickly whenever it would not remove any bits
1915 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1916 if (!(permutation & j))
1919 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1920 if (!r_glsl_permutation->compiled)
1921 R_GLSL_CompilePermutation(perm, mode, permutation);
1922 if (r_glsl_permutation->program)
1925 if (i >= SHADERPERMUTATION_COUNT)
1927 Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
1928 Cvar_SetValueQuick(&r_glsl, 0);
1929 R_GLSL_Restart_f(); // unload shaders
1930 return; // no bit left to clear
1935 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1939 void R_SetupGenericShader(qboolean usetexture)
1941 if (gl_support_fragment_shader)
1943 if (r_glsl.integer && r_glsl_usegeneric.integer)
1944 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1945 else if (r_glsl_permutation)
1947 r_glsl_permutation = NULL;
1948 qglUseProgramObjectARB(0);CHECKGLERROR
1953 void R_SetupGenericTwoTextureShader(int texturemode)
1955 if (gl_support_fragment_shader)
1957 if (r_glsl.integer && r_glsl_usegeneric.integer)
1958 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1959 else if (r_glsl_permutation)
1961 r_glsl_permutation = NULL;
1962 qglUseProgramObjectARB(0);CHECKGLERROR
1965 if (!r_glsl_permutation)
1967 if (texturemode == GL_DECAL && gl_combine.integer)
1968 texturemode = GL_INTERPOLATE_ARB;
1969 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1973 void R_SetupDepthOrShadowShader(void)
1975 if (gl_support_fragment_shader)
1977 if (r_glsl.integer && r_glsl_usegeneric.integer)
1978 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1979 else if (r_glsl_permutation)
1981 r_glsl_permutation = NULL;
1982 qglUseProgramObjectARB(0);CHECKGLERROR
1987 void R_SetupShowDepthShader(void)
1989 if (gl_support_fragment_shader)
1991 if (r_glsl.integer && r_glsl_usegeneric.integer)
1992 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
1993 else if (r_glsl_permutation)
1995 r_glsl_permutation = NULL;
1996 qglUseProgramObjectARB(0);CHECKGLERROR
2001 extern rtexture_t *r_shadow_attenuationgradienttexture;
2002 extern rtexture_t *r_shadow_attenuation2dtexture;
2003 extern rtexture_t *r_shadow_attenuation3dtexture;
2004 extern qboolean r_shadow_usingshadowmaprect;
2005 extern qboolean r_shadow_usingshadowmapcube;
2006 extern qboolean r_shadow_usingshadowmap2d;
2007 extern float r_shadow_shadowmap_texturescale[2];
2008 extern float r_shadow_shadowmap_parameters[4];
2009 extern qboolean r_shadow_shadowmapvsdct;
2010 extern qboolean r_shadow_shadowmapsampler;
2011 extern int r_shadow_shadowmappcf;
2012 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2014 // select a permutation of the lighting shader appropriate to this
2015 // combination of texture, entity, light source, and fogging, only use the
2016 // minimum features necessary to avoid wasting rendering time in the
2017 // fragment shader on features that are not being used
2018 unsigned int permutation = 0;
2019 unsigned int mode = 0;
2020 // TODO: implement geometry-shader based shadow volumes someday
2021 if (r_glsl_offsetmapping.integer)
2023 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2024 if (r_glsl_offsetmapping_reliefmapping.integer)
2025 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2027 if (rsurfacepass == RSURFPASS_BACKGROUND)
2029 // distorted background
2030 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2031 mode = SHADERMODE_WATER;
2033 mode = SHADERMODE_REFRACTION;
2035 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2038 mode = SHADERMODE_LIGHTSOURCE;
2039 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2040 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2041 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2042 permutation |= SHADERPERMUTATION_CUBEFILTER;
2043 if (diffusescale > 0)
2044 permutation |= SHADERPERMUTATION_DIFFUSE;
2045 if (specularscale > 0)
2046 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2047 if (r_refdef.fogenabled)
2048 permutation |= SHADERPERMUTATION_FOG;
2049 if (rsurface.texture->colormapping)
2050 permutation |= SHADERPERMUTATION_COLORMAPPING;
2051 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2053 if (r_shadow_usingshadowmaprect)
2054 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2055 if (r_shadow_usingshadowmap2d)
2056 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2057 if (r_shadow_usingshadowmapcube)
2058 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2059 else if(r_shadow_shadowmapvsdct)
2060 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2062 if (r_shadow_shadowmapsampler)
2063 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2064 if (r_shadow_shadowmappcf > 1)
2065 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2066 else if (r_shadow_shadowmappcf)
2067 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2070 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2072 // unshaded geometry (fullbright or ambient model lighting)
2073 mode = SHADERMODE_FLATCOLOR;
2074 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2075 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2076 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2077 permutation |= SHADERPERMUTATION_GLOW;
2078 if (r_refdef.fogenabled)
2079 permutation |= SHADERPERMUTATION_FOG;
2080 if (rsurface.texture->colormapping)
2081 permutation |= SHADERPERMUTATION_COLORMAPPING;
2082 if (r_glsl_offsetmapping.integer)
2084 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2085 if (r_glsl_offsetmapping_reliefmapping.integer)
2086 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2088 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2089 permutation |= SHADERPERMUTATION_REFLECTION;
2091 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2093 // directional model lighting
2094 mode = SHADERMODE_LIGHTDIRECTION;
2095 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2096 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2097 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2098 permutation |= SHADERPERMUTATION_GLOW;
2099 permutation |= SHADERPERMUTATION_DIFFUSE;
2100 if (specularscale > 0)
2101 permutation |= SHADERPERMUTATION_SPECULAR;
2102 if (r_refdef.fogenabled)
2103 permutation |= SHADERPERMUTATION_FOG;
2104 if (rsurface.texture->colormapping)
2105 permutation |= SHADERPERMUTATION_COLORMAPPING;
2106 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2107 permutation |= SHADERPERMUTATION_REFLECTION;
2109 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2111 // ambient model lighting
2112 mode = SHADERMODE_LIGHTDIRECTION;
2113 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2114 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2115 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2116 permutation |= SHADERPERMUTATION_GLOW;
2117 if (r_refdef.fogenabled)
2118 permutation |= SHADERPERMUTATION_FOG;
2119 if (rsurface.texture->colormapping)
2120 permutation |= SHADERPERMUTATION_COLORMAPPING;
2121 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2122 permutation |= SHADERPERMUTATION_REFLECTION;
2127 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2129 // deluxemapping (light direction texture)
2130 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2131 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2133 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2134 permutation |= SHADERPERMUTATION_DIFFUSE;
2135 if (specularscale > 0)
2136 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2138 else if (r_glsl_deluxemapping.integer >= 2)
2140 // fake deluxemapping (uniform light direction in tangentspace)
2141 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2142 permutation |= SHADERPERMUTATION_DIFFUSE;
2143 if (specularscale > 0)
2144 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2146 else if (rsurface.uselightmaptexture)
2148 // ordinary lightmapping (q1bsp, q3bsp)
2149 mode = SHADERMODE_LIGHTMAP;
2153 // ordinary vertex coloring (q3bsp)
2154 mode = SHADERMODE_VERTEXCOLOR;
2156 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2157 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2158 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2159 permutation |= SHADERPERMUTATION_GLOW;
2160 if (r_refdef.fogenabled)
2161 permutation |= SHADERPERMUTATION_FOG;
2162 if (rsurface.texture->colormapping)
2163 permutation |= SHADERPERMUTATION_COLORMAPPING;
2164 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2165 permutation |= SHADERPERMUTATION_REFLECTION;
2167 if(permutation & SHADERPERMUTATION_SPECULAR)
2168 if(r_shadow_glossexact.integer)
2169 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2170 R_SetupShader_SetPermutation(mode, permutation);
2171 if (mode == SHADERMODE_LIGHTSOURCE)
2173 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2174 if (permutation & SHADERPERMUTATION_DIFFUSE)
2176 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2177 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2178 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2179 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2183 // ambient only is simpler
2184 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
2185 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2186 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2187 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2189 // additive passes are only darkened by fog, not tinted
2190 if (r_glsl_permutation->loc_FogColor >= 0)
2191 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2192 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2193 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2197 if (mode == SHADERMODE_LIGHTDIRECTION)
2199 if (r_glsl_permutation->loc_AmbientColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * 0.5f, rsurface.modellight_ambient[1] * ambientscale * 0.5f, rsurface.modellight_ambient[2] * ambientscale * 0.5f);
2200 if (r_glsl_permutation->loc_DiffuseColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * 0.5f);
2201 if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
2202 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2206 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2207 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2208 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2210 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
2211 if (r_glsl_permutation->loc_GlowColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_GlowColor, rsurface.glowmod[0] * r_hdr_glowintensity.value, rsurface.glowmod[1] * r_hdr_glowintensity.value, rsurface.glowmod[2] * r_hdr_glowintensity.value);
2212 // additive passes are only darkened by fog, not tinted
2213 if (r_glsl_permutation->loc_FogColor >= 0)
2215 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2216 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2218 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2220 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2221 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2222 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2223 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2224 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2225 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2226 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2228 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2229 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2230 if (r_glsl_permutation->loc_Color_Pants >= 0)
2232 if (rsurface.texture->currentskinframe->pants)
2233 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2235 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2237 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2239 if (rsurface.texture->currentskinframe->shirt)
2240 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2242 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2244 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2245 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2247 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2251 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2253 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2257 #define SKINFRAME_HASH 1024
2261 int loadsequence; // incremented each level change
2262 memexpandablearray_t array;
2263 skinframe_t *hash[SKINFRAME_HASH];
2266 r_skinframe_t r_skinframe;
2268 void R_SkinFrame_PrepareForPurge(void)
2270 r_skinframe.loadsequence++;
2271 // wrap it without hitting zero
2272 if (r_skinframe.loadsequence >= 200)
2273 r_skinframe.loadsequence = 1;
2276 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2280 // mark the skinframe as used for the purging code
2281 skinframe->loadsequence = r_skinframe.loadsequence;
2284 void R_SkinFrame_Purge(void)
2288 for (i = 0;i < SKINFRAME_HASH;i++)
2290 for (s = r_skinframe.hash[i];s;s = s->next)
2292 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2294 if (s->merged == s->base)
2296 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2297 R_PurgeTexture(s->stain );s->stain = NULL;
2298 R_PurgeTexture(s->merged);s->merged = NULL;
2299 R_PurgeTexture(s->base );s->base = NULL;
2300 R_PurgeTexture(s->pants );s->pants = NULL;
2301 R_PurgeTexture(s->shirt );s->shirt = NULL;
2302 R_PurgeTexture(s->nmap );s->nmap = NULL;
2303 R_PurgeTexture(s->gloss );s->gloss = NULL;
2304 R_PurgeTexture(s->glow );s->glow = NULL;
2305 R_PurgeTexture(s->fog );s->fog = NULL;
2306 s->loadsequence = 0;
2312 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2314 char basename[MAX_QPATH];
2316 Image_StripImageExtension(name, basename, sizeof(basename));
2318 if( last == NULL ) {
2320 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2321 item = r_skinframe.hash[hashindex];
2326 // linearly search through the hash bucket
2327 for( ; item ; item = item->next ) {
2328 if( !strcmp( item->basename, basename ) ) {
2335 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2339 char basename[MAX_QPATH];
2341 Image_StripImageExtension(name, basename, sizeof(basename));
2343 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2344 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2345 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2349 rtexture_t *dyntexture;
2350 // check whether its a dynamic texture
2351 dyntexture = CL_GetDynTexture( basename );
2352 if (!add && !dyntexture)
2354 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2355 memset(item, 0, sizeof(*item));
2356 strlcpy(item->basename, basename, sizeof(item->basename));
2357 item->base = dyntexture; // either NULL or dyntexture handle
2358 item->textureflags = textureflags;
2359 item->comparewidth = comparewidth;
2360 item->compareheight = compareheight;
2361 item->comparecrc = comparecrc;
2362 item->next = r_skinframe.hash[hashindex];
2363 r_skinframe.hash[hashindex] = item;
2365 else if( item->base == NULL )
2367 rtexture_t *dyntexture;
2368 // check whether its a dynamic texture
2369 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
2370 dyntexture = CL_GetDynTexture( basename );
2371 item->base = dyntexture; // either NULL or dyntexture handle
2374 R_SkinFrame_MarkUsed(item);
2378 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2380 unsigned long long avgcolor[5], wsum; \
2388 for(pix = 0; pix < cnt; ++pix) \
2391 for(comp = 0; comp < 3; ++comp) \
2393 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2396 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2398 for(comp = 0; comp < 3; ++comp) \
2399 avgcolor[comp] += getpixel * w; \
2402 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2403 avgcolor[4] += getpixel; \
2405 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2407 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2408 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2409 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2410 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2413 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2415 // FIXME: it should be possible to disable loading various layers using
2416 // cvars, to prevent wasted loading time and memory usage if the user does
2418 qboolean loadnormalmap = true;
2419 qboolean loadgloss = true;
2420 qboolean loadpantsandshirt = true;
2421 qboolean loadglow = true;
2423 unsigned char *pixels;
2424 unsigned char *bumppixels;
2425 unsigned char *basepixels = NULL;
2426 int basepixels_width;
2427 int basepixels_height;
2428 skinframe_t *skinframe;
2433 if (cls.state == ca_dedicated)
2436 // return an existing skinframe if already loaded
2437 // if loading of the first image fails, don't make a new skinframe as it
2438 // would cause all future lookups of this to be missing
2439 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2440 if (skinframe && skinframe->base)
2443 basepixels = loadimagepixelsbgra(name, complain, true);
2444 if (basepixels == NULL)
2447 if (developer_loading.integer)
2448 Con_Printf("loading skin \"%s\"\n", name);
2450 // we've got some pixels to store, so really allocate this new texture now
2452 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2453 skinframe->stain = NULL;
2454 skinframe->merged = NULL;
2455 skinframe->base = r_texture_notexture;
2456 skinframe->pants = NULL;
2457 skinframe->shirt = NULL;
2458 skinframe->nmap = r_texture_blanknormalmap;
2459 skinframe->gloss = NULL;
2460 skinframe->glow = NULL;
2461 skinframe->fog = NULL;
2463 basepixels_width = image_width;
2464 basepixels_height = image_height;
2465 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2467 if (textureflags & TEXF_ALPHA)
2469 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2470 if (basepixels[j] < 255)
2472 if (j < basepixels_width * basepixels_height * 4)
2474 // has transparent pixels
2477 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2478 for (j = 0;j < image_width * image_height * 4;j += 4)
2483 pixels[j+3] = basepixels[j+3];
2485 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2490 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2491 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2493 // _norm is the name used by tenebrae and has been adopted as standard
2496 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2498 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2502 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2504 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2505 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2506 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2508 Mem_Free(bumppixels);
2510 else if (r_shadow_bumpscale_basetexture.value > 0)
2512 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2513 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2514 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2518 // _luma is supported for tenebrae compatibility
2519 // (I think it's a very stupid name, but oh well)
2520 // _glow is the preferred name
2521 if (loadglow && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2522 if (loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2523 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2524 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
2527 Mem_Free(basepixels);
2532 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2534 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL);
2537 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
2542 for (i = 0;i < width*height;i++)
2543 if (((unsigned char *)&palette[in[i]])[3] > 0)
2545 if (i == width*height)
2548 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2551 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2552 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2555 unsigned char *temp1, *temp2;
2556 skinframe_t *skinframe;
2558 if (cls.state == ca_dedicated)
2561 // if already loaded just return it, otherwise make a new skinframe
2562 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2563 if (skinframe && skinframe->base)
2566 skinframe->stain = NULL;
2567 skinframe->merged = NULL;
2568 skinframe->base = r_texture_notexture;
2569 skinframe->pants = NULL;
2570 skinframe->shirt = NULL;
2571 skinframe->nmap = r_texture_blanknormalmap;
2572 skinframe->gloss = NULL;
2573 skinframe->glow = NULL;
2574 skinframe->fog = NULL;
2576 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2580 if (developer_loading.integer)
2581 Con_Printf("loading 32bit skin \"%s\"\n", name);
2583 if (r_shadow_bumpscale_basetexture.value > 0)
2585 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2586 temp2 = temp1 + width * height * 4;
2587 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2588 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2591 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2592 if (textureflags & TEXF_ALPHA)
2594 for (i = 3;i < width * height * 4;i += 4)
2595 if (skindata[i] < 255)
2597 if (i < width * height * 4)
2599 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2600 memcpy(fogpixels, skindata, width * height * 4);
2601 for (i = 0;i < width * height * 4;i += 4)
2602 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2603 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2604 Mem_Free(fogpixels);
2608 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2609 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2614 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2617 unsigned char *temp1, *temp2;
2618 unsigned int *palette;
2619 skinframe_t *skinframe;
2621 if (cls.state == ca_dedicated)
2624 // if already loaded just return it, otherwise make a new skinframe
2625 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2626 if (skinframe && skinframe->base)
2629 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2631 skinframe->stain = NULL;
2632 skinframe->merged = NULL;
2633 skinframe->base = r_texture_notexture;
2634 skinframe->pants = NULL;
2635 skinframe->shirt = NULL;
2636 skinframe->nmap = r_texture_blanknormalmap;
2637 skinframe->gloss = NULL;
2638 skinframe->glow = NULL;
2639 skinframe->fog = NULL;
2641 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2645 if (developer_loading.integer)
2646 Con_Printf("loading quake skin \"%s\"\n", name);
2648 if (r_shadow_bumpscale_basetexture.value > 0)
2650 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2651 temp2 = temp1 + width * height * 4;
2652 // use either a custom palette or the quake palette
2653 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2654 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2655 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2658 // use either a custom palette, or the quake palette
2659 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2660 if (loadglowtexture)
2661 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2662 if (loadpantsandshirt)
2664 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2665 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2667 if (skinframe->pants || skinframe->shirt)
2668 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
2669 if (textureflags & TEXF_ALPHA)
2671 for (i = 0;i < width * height;i++)
2672 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2674 if (i < width * height)
2675 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2678 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2679 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2684 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
2687 skinframe_t *skinframe;
2689 if (cls.state == ca_dedicated)
2692 // if already loaded just return it, otherwise make a new skinframe
2693 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2694 if (skinframe && skinframe->base)
2697 skinframe->stain = NULL;
2698 skinframe->merged = NULL;
2699 skinframe->base = r_texture_notexture;
2700 skinframe->pants = NULL;
2701 skinframe->shirt = NULL;
2702 skinframe->nmap = r_texture_blanknormalmap;
2703 skinframe->gloss = NULL;
2704 skinframe->glow = NULL;
2705 skinframe->fog = NULL;
2707 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2711 if (developer_loading.integer)
2712 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2714 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, skinframe->basename, palette, skinframe->textureflags, true);
2715 if (textureflags & TEXF_ALPHA)
2717 for (i = 0;i < width * height;i++)
2718 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
2720 if (i < width * height)
2721 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
2724 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2725 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2730 skinframe_t *R_SkinFrame_LoadMissing(void)
2732 skinframe_t *skinframe;
2734 if (cls.state == ca_dedicated)
2737 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2738 skinframe->stain = NULL;
2739 skinframe->merged = NULL;
2740 skinframe->base = r_texture_notexture;
2741 skinframe->pants = NULL;
2742 skinframe->shirt = NULL;
2743 skinframe->nmap = r_texture_blanknormalmap;
2744 skinframe->gloss = NULL;
2745 skinframe->glow = NULL;
2746 skinframe->fog = NULL;
2748 skinframe->avgcolor[0] = rand() / RAND_MAX;
2749 skinframe->avgcolor[1] = rand() / RAND_MAX;
2750 skinframe->avgcolor[2] = rand() / RAND_MAX;
2751 skinframe->avgcolor[3] = 1;
2756 void gl_main_start(void)
2760 memset(r_queries, 0, sizeof(r_queries));
2762 r_qwskincache = NULL;
2763 r_qwskincache_size = 0;
2765 // set up r_skinframe loading system for textures
2766 memset(&r_skinframe, 0, sizeof(r_skinframe));
2767 r_skinframe.loadsequence = 1;
2768 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2770 r_main_texturepool = R_AllocTexturePool();
2771 R_BuildBlankTextures();
2773 if (gl_texturecubemap)
2776 R_BuildNormalizationCube();
2778 r_texture_fogattenuation = NULL;
2779 r_texture_gammaramps = NULL;
2780 //r_texture_fogintensity = NULL;
2781 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2782 memset(&r_waterstate, 0, sizeof(r_waterstate));
2783 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2784 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2785 memset(&r_svbsp, 0, sizeof (r_svbsp));
2787 r_refdef.fogmasktable_density = 0;
2790 extern rtexture_t *loadingscreentexture;
2791 void gl_main_shutdown(void)
2794 qglDeleteQueriesARB(r_maxqueries, r_queries);
2798 memset(r_queries, 0, sizeof(r_queries));
2800 r_qwskincache = NULL;
2801 r_qwskincache_size = 0;
2803 // clear out the r_skinframe state
2804 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2805 memset(&r_skinframe, 0, sizeof(r_skinframe));
2808 Mem_Free(r_svbsp.nodes);
2809 memset(&r_svbsp, 0, sizeof (r_svbsp));
2810 R_FreeTexturePool(&r_main_texturepool);
2811 loadingscreentexture = NULL;
2812 r_texture_blanknormalmap = NULL;
2813 r_texture_white = NULL;
2814 r_texture_grey128 = NULL;
2815 r_texture_black = NULL;
2816 r_texture_whitecube = NULL;
2817 r_texture_normalizationcube = NULL;
2818 r_texture_fogattenuation = NULL;
2819 r_texture_gammaramps = NULL;
2820 //r_texture_fogintensity = NULL;
2821 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2822 memset(&r_waterstate, 0, sizeof(r_waterstate));
2826 extern void CL_ParseEntityLump(char *entitystring);
2827 void gl_main_newmap(void)
2829 // FIXME: move this code to client
2831 char *entities, entname[MAX_QPATH];
2833 Mem_Free(r_qwskincache);
2834 r_qwskincache = NULL;
2835 r_qwskincache_size = 0;
2838 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2839 l = (int)strlen(entname) - 4;
2840 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2842 memcpy(entname + l, ".ent", 5);
2843 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2845 CL_ParseEntityLump(entities);
2850 if (cl.worldmodel->brush.entities)
2851 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2855 void GL_Main_Init(void)
2857 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2859 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2860 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2861 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2862 if (gamemode == GAME_NEHAHRA)
2864 Cvar_RegisterVariable (&gl_fogenable);
2865 Cvar_RegisterVariable (&gl_fogdensity);
2866 Cvar_RegisterVariable (&gl_fogred);
2867 Cvar_RegisterVariable (&gl_foggreen);
2868 Cvar_RegisterVariable (&gl_fogblue);
2869 Cvar_RegisterVariable (&gl_fogstart);
2870 Cvar_RegisterVariable (&gl_fogend);
2871 Cvar_RegisterVariable (&gl_skyclip);
2873 Cvar_RegisterVariable(&r_motionblur);
2874 Cvar_RegisterVariable(&r_motionblur_maxblur);
2875 Cvar_RegisterVariable(&r_motionblur_bmin);
2876 Cvar_RegisterVariable(&r_motionblur_vmin);
2877 Cvar_RegisterVariable(&r_motionblur_vmax);
2878 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2879 Cvar_RegisterVariable(&r_motionblur_randomize);
2880 Cvar_RegisterVariable(&r_damageblur);
2881 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
2882 Cvar_RegisterVariable(&r_equalize_entities_minambient);
2883 Cvar_RegisterVariable(&r_equalize_entities_by);
2884 Cvar_RegisterVariable(&r_equalize_entities_to);
2885 Cvar_RegisterVariable(&r_animcache);
2886 Cvar_RegisterVariable(&r_depthfirst);
2887 Cvar_RegisterVariable(&r_useinfinitefarclip);
2888 Cvar_RegisterVariable(&r_nearclip);
2889 Cvar_RegisterVariable(&r_showbboxes);
2890 Cvar_RegisterVariable(&r_showsurfaces);
2891 Cvar_RegisterVariable(&r_showtris);
2892 Cvar_RegisterVariable(&r_shownormals);
2893 Cvar_RegisterVariable(&r_showlighting);
2894 Cvar_RegisterVariable(&r_showshadowvolumes);
2895 Cvar_RegisterVariable(&r_showcollisionbrushes);
2896 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2897 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2898 Cvar_RegisterVariable(&r_showdisabledepthtest);
2899 Cvar_RegisterVariable(&r_drawportals);
2900 Cvar_RegisterVariable(&r_drawentities);
2901 Cvar_RegisterVariable(&r_cullentities_trace);
2902 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2903 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2904 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2905 Cvar_RegisterVariable(&r_drawviewmodel);
2906 Cvar_RegisterVariable(&r_speeds);
2907 Cvar_RegisterVariable(&r_fullbrights);
2908 Cvar_RegisterVariable(&r_wateralpha);
2909 Cvar_RegisterVariable(&r_dynamic);
2910 Cvar_RegisterVariable(&r_fullbright);
2911 Cvar_RegisterVariable(&r_shadows);
2912 Cvar_RegisterVariable(&r_shadows_darken);
2913 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
2914 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2915 Cvar_RegisterVariable(&r_shadows_throwdistance);
2916 Cvar_RegisterVariable(&r_shadows_throwdirection);
2917 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2918 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2919 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2920 Cvar_RegisterVariable(&r_fog_exp2);
2921 Cvar_RegisterVariable(&r_drawfog);
2922 Cvar_RegisterVariable(&r_textureunits);
2923 Cvar_RegisterVariable(&r_glsl);
2924 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2925 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2926 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2927 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2928 Cvar_RegisterVariable(&r_glsl_postprocess);
2929 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2930 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2931 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2932 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2933 Cvar_RegisterVariable(&r_glsl_usegeneric);
2934 Cvar_RegisterVariable(&r_water);
2935 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2936 Cvar_RegisterVariable(&r_water_clippingplanebias);
2937 Cvar_RegisterVariable(&r_water_refractdistort);
2938 Cvar_RegisterVariable(&r_water_reflectdistort);
2939 Cvar_RegisterVariable(&r_lerpsprites);
2940 Cvar_RegisterVariable(&r_lerpmodels);
2941 Cvar_RegisterVariable(&r_lerplightstyles);
2942 Cvar_RegisterVariable(&r_waterscroll);
2943 Cvar_RegisterVariable(&r_bloom);
2944 Cvar_RegisterVariable(&r_bloom_colorscale);
2945 Cvar_RegisterVariable(&r_bloom_brighten);
2946 Cvar_RegisterVariable(&r_bloom_blur);
2947 Cvar_RegisterVariable(&r_bloom_resolution);
2948 Cvar_RegisterVariable(&r_bloom_colorexponent);
2949 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2950 Cvar_RegisterVariable(&r_hdr);
2951 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2952 Cvar_RegisterVariable(&r_hdr_glowintensity);
2953 Cvar_RegisterVariable(&r_hdr_range);
2954 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2955 Cvar_RegisterVariable(&developer_texturelogging);
2956 Cvar_RegisterVariable(&gl_lightmaps);
2957 Cvar_RegisterVariable(&r_test);
2958 Cvar_RegisterVariable(&r_batchmode);
2959 Cvar_RegisterVariable(&r_glsl_saturation);
2960 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2961 Cvar_SetValue("r_fullbrights", 0);
2962 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2964 Cvar_RegisterVariable(&r_track_sprites);
2965 Cvar_RegisterVariable(&r_track_sprites_flags);
2966 Cvar_RegisterVariable(&r_track_sprites_scalew);
2967 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2970 extern void R_Textures_Init(void);
2971 extern void GL_Draw_Init(void);
2972 extern void GL_Main_Init(void);
2973 extern void R_Shadow_Init(void);
2974 extern void R_Sky_Init(void);
2975 extern void GL_Surf_Init(void);
2976 extern void R_Particles_Init(void);
2977 extern void R_Explosion_Init(void);
2978 extern void gl_backend_init(void);
2979 extern void Sbar_Init(void);
2980 extern void R_LightningBeams_Init(void);
2981 extern void Mod_RenderInit(void);
2983 void Render_Init(void)
2995 R_LightningBeams_Init();
3004 extern char *ENGINE_EXTENSIONS;
3007 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3008 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3009 gl_version = (const char *)qglGetString(GL_VERSION);
3010 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3014 if (!gl_platformextensions)
3015 gl_platformextensions = "";
3017 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3018 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3019 Con_Printf("GL_VERSION: %s\n", gl_version);
3020 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3021 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3023 VID_CheckExtensions();
3025 // LordHavoc: report supported extensions
3026 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3028 // clear to black (loading plaque will be seen over this)
3030 qglClearColor(0,0,0,1);CHECKGLERROR
3031 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3034 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3038 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3040 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3043 p = r_refdef.view.frustum + i;
3048 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3052 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3056 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3060 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3064 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3068 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3072 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3076 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3084 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3088 for (i = 0;i < numplanes;i++)
3095 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3099 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3103 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3107 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3111 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3115 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3119 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3123 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3131 //==================================================================================
3133 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3136 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3137 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3138 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3141 typedef struct r_animcache_entity_s
3148 qboolean wantnormals;
3149 qboolean wanttangents;
3151 r_animcache_entity_t;
3153 typedef struct r_animcache_s
3155 r_animcache_entity_t entity[MAX_EDICTS*2];
3161 static r_animcache_t r_animcachestate;
3163 void R_AnimCache_Free(void)
3166 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3168 r_animcachestate.entity[idx].maxvertices = 0;
3169 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3170 r_animcachestate.entity[idx].vertex3f = NULL;
3171 r_animcachestate.entity[idx].normal3f = NULL;
3172 r_animcachestate.entity[idx].svector3f = NULL;
3173 r_animcachestate.entity[idx].tvector3f = NULL;
3175 r_animcachestate.currentindex = 0;
3176 r_animcachestate.maxindex = 0;
3179 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3183 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3185 if (cache->maxvertices >= numvertices)
3188 // Release existing memory
3189 if (cache->vertex3f)
3190 Mem_Free(cache->vertex3f);
3192 // Pad by 1024 verts
3193 cache->maxvertices = (numvertices + 1023) & ~1023;
3194 arraySize = cache->maxvertices * 3;
3196 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3197 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3198 r_animcachestate.entity[cacheIdx].vertex3f = base;
3199 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3200 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3201 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3203 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3206 void R_AnimCache_NewFrame(void)
3210 if (r_animcache.integer && r_drawentities.integer)
3211 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3212 else if (r_animcachestate.maxindex)
3215 r_animcachestate.currentindex = 0;
3217 for (i = 0;i < r_refdef.scene.numentities;i++)
3218 r_refdef.scene.entities[i]->animcacheindex = -1;
3221 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3223 dp_model_t *model = ent->model;
3224 r_animcache_entity_t *c;
3225 // see if it's already cached this frame
3226 if (ent->animcacheindex >= 0)
3228 // add normals/tangents if needed
3229 c = r_animcachestate.entity + ent->animcacheindex;
3231 wantnormals = false;
3232 if (c->wanttangents)
3233 wanttangents = false;
3234 if (wantnormals || wanttangents)
3235 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3239 // see if this ent is worth caching
3240 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3242 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3244 // assign it a cache entry and make sure the arrays are big enough
3245 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3246 ent->animcacheindex = r_animcachestate.currentindex++;
3247 c = r_animcachestate.entity + ent->animcacheindex;
3248 c->wantnormals = wantnormals;
3249 c->wanttangents = wanttangents;
3250 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3255 void R_AnimCache_CacheVisibleEntities(void)
3258 qboolean wantnormals;
3259 qboolean wanttangents;
3261 if (!r_animcachestate.maxindex)
3264 wantnormals = !r_showsurfaces.integer;
3265 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3267 // TODO: thread this?
3269 for (i = 0;i < r_refdef.scene.numentities;i++)
3271 if (!r_refdef.viewcache.entityvisible[i])
3273 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3277 //==================================================================================
3279 static void R_View_UpdateEntityLighting (void)
3282 entity_render_t *ent;
3283 vec3_t tempdiffusenormal, avg;
3284 vec_t f, fa, fd, fdd;
3286 for (i = 0;i < r_refdef.scene.numentities;i++)
3288 ent = r_refdef.scene.entities[i];
3290 // skip unseen models
3291 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3295 if (ent->model && ent->model->brush.num_leafs)
3297 // TODO: use modellight for r_ambient settings on world?
3298 VectorSet(ent->modellight_ambient, 0, 0, 0);
3299 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3300 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3304 // fetch the lighting from the worldmodel data
3305 VectorSet(ent->modellight_ambient, r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f));
3306 VectorClear(ent->modellight_diffuse);
3307 VectorClear(tempdiffusenormal);
3308 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3311 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3312 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3313 if(ent->flags & RENDER_EQUALIZE)
3315 // first fix up ambient lighting...
3316 if(r_equalize_entities_minambient.value > 0)
3318 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3321 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3322 if(fa < r_equalize_entities_minambient.value * fd)
3325 // fa'/fd' = minambient
3326 // fa'+0.25*fd' = fa+0.25*fd
3328 // fa' = fd' * minambient
3329 // fd'*(0.25+minambient) = fa+0.25*fd
3331 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3332 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3334 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3335 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
3336 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3337 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3342 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3344 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3345 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3348 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3349 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3350 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3356 VectorSet(ent->modellight_ambient, 1, 1, 1);
3358 // move the light direction into modelspace coordinates for lighting code
3359 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3360 if(VectorLength2(ent->modellight_lightdir) == 0)
3361 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3362 VectorNormalize(ent->modellight_lightdir);
3366 #define MAX_LINEOFSIGHTTRACES 64
3368 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3371 vec3_t boxmins, boxmaxs;
3374 dp_model_t *model = r_refdef.scene.worldmodel;
3376 if (!model || !model->brush.TraceLineOfSight)
3379 // expand the box a little
3380 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3381 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3382 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3383 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3384 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3385 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3388 VectorCopy(eye, start);
3389 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3390 if (model->brush.TraceLineOfSight(model, start, end))
3393 // try various random positions
3394 for (i = 0;i < numsamples;i++)
3396 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3397 if (model->brush.TraceLineOfSight(model, start, end))
3405 static void R_View_UpdateEntityVisible (void)
3408 entity_render_t *ent;
3410 if (!r_drawentities.integer)
3413 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3414 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3416 // worldmodel can check visibility
3417 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3418 for (i = 0;i < r_refdef.scene.numentities;i++)
3420 ent = r_refdef.scene.entities[i];
3421 if (!(ent->flags & renderimask))
3422 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
3423 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
3424 r_refdef.viewcache.entityvisible[i] = true;
3426 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3428 for (i = 0;i < r_refdef.scene.numentities;i++)
3430 ent = r_refdef.scene.entities[i];
3431 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3433 if(R_CanSeeBox(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3434 ent->last_trace_visibility = realtime;
3435 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3436 r_refdef.viewcache.entityvisible[i] = 0;
3443 // no worldmodel or it can't check visibility
3444 for (i = 0;i < r_refdef.scene.numentities;i++)
3446 ent = r_refdef.scene.entities[i];
3447 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
3452 /// only used if skyrendermasked, and normally returns false
3453 int R_DrawBrushModelsSky (void)
3456 entity_render_t *ent;
3458 if (!r_drawentities.integer)
3462 for (i = 0;i < r_refdef.scene.numentities;i++)
3464 if (!r_refdef.viewcache.entityvisible[i])
3466 ent = r_refdef.scene.entities[i];
3467 if (!ent->model || !ent->model->DrawSky)
3469 ent->model->DrawSky(ent);
3475 static void R_DrawNoModel(entity_render_t *ent);
3476 static void R_DrawModels(void)
3479 entity_render_t *ent;
3481 if (!r_drawentities.integer)
3484 for (i = 0;i < r_refdef.scene.numentities;i++)
3486 if (!r_refdef.viewcache.entityvisible[i])
3488 ent = r_refdef.scene.entities[i];
3489 r_refdef.stats.entities++;
3490 if (ent->model && ent->model->Draw != NULL)
3491 ent->model->Draw(ent);
3497 static void R_DrawModelsDepth(void)
3500 entity_render_t *ent;
3502 if (!r_drawentities.integer)
3505 for (i = 0;i < r_refdef.scene.numentities;i++)
3507 if (!r_refdef.viewcache.entityvisible[i])
3509 ent = r_refdef.scene.entities[i];
3510 if (ent->model && ent->model->DrawDepth != NULL)
3511 ent->model->DrawDepth(ent);
3515 static void R_DrawModelsDebug(void)
3518 entity_render_t *ent;
3520 if (!r_drawentities.integer)
3523 for (i = 0;i < r_refdef.scene.numentities;i++)
3525 if (!r_refdef.viewcache.entityvisible[i])
3527 ent = r_refdef.scene.entities[i];
3528 if (ent->model && ent->model->DrawDebug != NULL)
3529 ent->model->DrawDebug(ent);
3533 static void R_DrawModelsAddWaterPlanes(void)
3536 entity_render_t *ent;
3538 if (!r_drawentities.integer)
3541 for (i = 0;i < r_refdef.scene.numentities;i++)
3543 if (!r_refdef.viewcache.entityvisible[i])
3545 ent = r_refdef.scene.entities[i];
3546 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3547 ent->model->DrawAddWaterPlanes(ent);
3551 static void R_View_SetFrustum(void)
3554 double slopex, slopey;
3555 vec3_t forward, left, up, origin;
3557 // we can't trust r_refdef.view.forward and friends in reflected scenes
3558 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3561 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3562 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3563 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3564 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3565 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3566 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3567 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3568 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3569 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3570 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3571 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3572 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3576 zNear = r_refdef.nearclip;
3577 nudge = 1.0 - 1.0 / (1<<23);
3578 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3579 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3580 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3581 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3582 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3583 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3584 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3585 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3591 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3592 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3593 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3594 r_refdef.view.frustum[0].dist = m[15] - m[12];
3596 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3597 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3598 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3599 r_refdef.view.frustum[1].dist = m[15] + m[12];
3601 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3602 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3603 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3604 r_refdef.view.frustum[2].dist = m[15] - m[13];
3606 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3607 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3608 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3609 r_refdef.view.frustum[3].dist = m[15] + m[13];
3611 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3612 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3613 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3614 r_refdef.view.frustum[4].dist = m[15] - m[14];
3616 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3617 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3618 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3619 r_refdef.view.frustum[5].dist = m[15] + m[14];
3622 if (r_refdef.view.useperspective)
3624 slopex = 1.0 / r_refdef.view.frustum_x;
3625 slopey = 1.0 / r_refdef.view.frustum_y;
3626 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3627 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3628 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3629 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3630 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3632 // Leaving those out was a mistake, those were in the old code, and they
3633 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3634 // I couldn't reproduce it after adding those normalizations. --blub
3635 VectorNormalize(r_refdef.view.frustum[0].normal);
3636 VectorNormalize(r_refdef.view.frustum[1].normal);
3637 VectorNormalize(r_refdef.view.frustum[2].normal);
3638 VectorNormalize(r_refdef.view.frustum[3].normal);
3640 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3641 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
3642 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
3643 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
3644 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
3646 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3647 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3648 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3649 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3650 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3654 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3655 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3656 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3657 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3658 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3659 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3660 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3661 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3662 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3663 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3665 r_refdef.view.numfrustumplanes = 5;
3667 if (r_refdef.view.useclipplane)
3669 r_refdef.view.numfrustumplanes = 6;
3670 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3673 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3674 PlaneClassify(r_refdef.view.frustum + i);
3676 // LordHavoc: note to all quake engine coders, Quake had a special case
3677 // for 90 degrees which assumed a square view (wrong), so I removed it,
3678 // Quake2 has it disabled as well.
3680 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3681 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3682 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3683 //PlaneClassify(&frustum[0]);
3685 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3686 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3687 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3688 //PlaneClassify(&frustum[1]);
3690 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3691 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3692 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3693 //PlaneClassify(&frustum[2]);
3695 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3696 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3697 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3698 //PlaneClassify(&frustum[3]);
3701 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3702 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3703 //PlaneClassify(&frustum[4]);
3706 void R_View_Update(void)
3708 R_View_SetFrustum();
3709 R_View_WorldVisibility(r_refdef.view.useclipplane);
3710 R_View_UpdateEntityVisible();
3711 R_View_UpdateEntityLighting();
3714 void R_SetupView(qboolean allowwaterclippingplane)
3716 const double *customclipplane = NULL;
3718 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3720 // LordHavoc: couldn't figure out how to make this approach the
3721 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3722 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3723 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3724 dist = r_refdef.view.clipplane.dist;
3725 plane[0] = r_refdef.view.clipplane.normal[0];
3726 plane[1] = r_refdef.view.clipplane.normal[1];
3727 plane[2] = r_refdef.view.clipplane.normal[2];
3729 customclipplane = plane;
3732 if (!r_refdef.view.useperspective)
3733 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
3734 else if (gl_stencil && r_useinfinitefarclip.integer)
3735 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
3737 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
3738 R_SetViewport(&r_refdef.view.viewport);
3741 void R_ResetViewRendering2D(void)
3743 r_viewport_t viewport;
3746 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3747 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
3748 R_SetViewport(&viewport);
3749 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3750 GL_Color(1, 1, 1, 1);
3751 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3752 GL_BlendFunc(GL_ONE, GL_ZERO);
3753 GL_AlphaTest(false);
3754 GL_ScissorTest(false);
3755 GL_DepthMask(false);
3756 GL_DepthRange(0, 1);
3757 GL_DepthTest(false);
3758 R_Mesh_Matrix(&identitymatrix);
3759 R_Mesh_ResetTextureState();
3760 GL_PolygonOffset(0, 0);
3761 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3762 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3763 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3764 qglStencilMask(~0);CHECKGLERROR
3765 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3766 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3767 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3768 R_SetupGenericShader(true);
3771 void R_ResetViewRendering3D(void)
3776 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3777 GL_Color(1, 1, 1, 1);
3778 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3779 GL_BlendFunc(GL_ONE, GL_ZERO);
3780 GL_AlphaTest(false);
3781 GL_ScissorTest(true);
3783 GL_DepthRange(0, 1);
3785 R_Mesh_Matrix(&identitymatrix);
3786 R_Mesh_ResetTextureState();
3787 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3788 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3789 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3790 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3791 qglStencilMask(~0);CHECKGLERROR
3792 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3793 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3794 GL_CullFace(r_refdef.view.cullface_back);
3795 R_SetupGenericShader(true);
3798 void R_RenderScene(void);
3799 void R_RenderWaterPlanes(void);
3801 static void R_Water_StartFrame(void)
3804 int waterwidth, waterheight, texturewidth, textureheight;
3805 r_waterstate_waterplane_t *p;
3807 // set waterwidth and waterheight to the water resolution that will be
3808 // used (often less than the screen resolution for faster rendering)
3809 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3810 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3812 // calculate desired texture sizes
3813 // can't use water if the card does not support the texture size
3814 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3815 texturewidth = textureheight = waterwidth = waterheight = 0;
3816 else if (gl_support_arb_texture_non_power_of_two)
3818 texturewidth = waterwidth;
3819 textureheight = waterheight;
3823 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3824 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3827 // allocate textures as needed
3828 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3830 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3831 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3833 if (p->texture_refraction)
3834 R_FreeTexture(p->texture_refraction);
3835 p->texture_refraction = NULL;
3836 if (p->texture_reflection)
3837 R_FreeTexture(p->texture_reflection);
3838 p->texture_reflection = NULL;
3840 memset(&r_waterstate, 0, sizeof(r_waterstate));
3841 r_waterstate.texturewidth = texturewidth;
3842 r_waterstate.textureheight = textureheight;
3845 if (r_waterstate.texturewidth)
3847 r_waterstate.enabled = true;
3849 // when doing a reduced render (HDR) we want to use a smaller area
3850 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3851 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3853 // set up variables that will be used in shader setup
3854 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3855 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3856 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3857 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3860 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3861 r_waterstate.numwaterplanes = 0;
3864 void R_Water_AddWaterPlane(msurface_t *surface)
3866 int triangleindex, planeindex;
3872 r_waterstate_waterplane_t *p;
3873 texture_t *t = R_GetCurrentTexture(surface->texture);
3874 // just use the first triangle with a valid normal for any decisions
3875 VectorClear(normal);
3876 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3878 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3879 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3880 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3881 TriangleNormal(vert[0], vert[1], vert[2], normal);
3882 if (VectorLength2(normal) >= 0.001)
3886 VectorCopy(normal, plane.normal);
3887 VectorNormalize(plane.normal);
3888 plane.dist = DotProduct(vert[0], plane.normal);
3889 PlaneClassify(&plane);
3890 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3892 // skip backfaces (except if nocullface is set)
3893 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3895 VectorNegate(plane.normal, plane.normal);
3897 PlaneClassify(&plane);
3901 // find a matching plane if there is one
3902 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3903 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3905 if (planeindex >= r_waterstate.maxwaterplanes)
3906 return; // nothing we can do, out of planes
3908 // if this triangle does not fit any known plane rendered this frame, add one
3909 if (planeindex >= r_waterstate.numwaterplanes)
3911 // store the new plane
3912 r_waterstate.numwaterplanes++;
3914 // clear materialflags and pvs
3915 p->materialflags = 0;
3916 p->pvsvalid = false;
3918 // merge this surface's materialflags into the waterplane
3919 p->materialflags |= t->currentmaterialflags;
3920 // merge this surface's PVS into the waterplane
3921 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3922 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3923 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3925 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3930 static void R_Water_ProcessPlanes(void)
3932 r_refdef_view_t originalview;
3933 r_refdef_view_t myview;
3935 r_waterstate_waterplane_t *p;
3937 originalview = r_refdef.view;
3939 // make sure enough textures are allocated
3940 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3942 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3944 if (!p->texture_refraction)
3945 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3946 if (!p->texture_refraction)
3950 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3952 if (!p->texture_reflection)
3953 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3954 if (!p->texture_reflection)
3960 r_refdef.view = originalview;
3961 r_refdef.view.showdebug = false;
3962 r_refdef.view.width = r_waterstate.waterwidth;
3963 r_refdef.view.height = r_waterstate.waterheight;
3964 r_refdef.view.useclipplane = true;
3965 myview = r_refdef.view;
3966 r_waterstate.renderingscene = true;
3967 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3969 // render the normal view scene and copy into texture
3970 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
3971 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3973 r_refdef.view = myview;
3974 r_refdef.view.clipplane = p->plane;
3975 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3976 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3977 PlaneClassify(&r_refdef.view.clipplane);
3979 R_ResetViewRendering3D();
3980 R_ClearScreen(r_refdef.fogenabled);
3984 // copy view into the screen texture
3985 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3986 GL_ActiveTexture(0);
3988 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
3991 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3993 r_refdef.view = myview;
3994 // render reflected scene and copy into texture
3995 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3996 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3997 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3998 r_refdef.view.clipplane = p->plane;
3999 // reverse the cullface settings for this render
4000 r_refdef.view.cullface_front = GL_FRONT;
4001 r_refdef.view.cullface_back = GL_BACK;
4002 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4004 r_refdef.view.usecustompvs = true;
4006 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4008 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4011 R_ResetViewRendering3D();
4012 R_ClearScreen(r_refdef.fogenabled);
4016 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4017 GL_ActiveTexture(0);
4019 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4022 r_waterstate.renderingscene = false;
4023 r_refdef.view = originalview;
4024 R_ResetViewRendering3D();
4025 R_ClearScreen(r_refdef.fogenabled);
4029 r_refdef.view = originalview;
4030 r_waterstate.renderingscene = false;
4031 Cvar_SetValueQuick(&r_water, 0);
4032 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4036 void R_Bloom_StartFrame(void)
4038 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4040 // set bloomwidth and bloomheight to the bloom resolution that will be
4041 // used (often less than the screen resolution for faster rendering)
4042 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4043 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4044 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4045 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
4046 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
4048 // calculate desired texture sizes
4049 if (gl_support_arb_texture_non_power_of_two)
4051 screentexturewidth = r_refdef.view.width;
4052 screentextureheight = r_refdef.view.height;
4053 bloomtexturewidth = r_bloomstate.bloomwidth;
4054 bloomtextureheight = r_bloomstate.bloomheight;
4058 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4059 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4060 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4061 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4064 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
4066 Cvar_SetValueQuick(&r_hdr, 0);
4067 Cvar_SetValueQuick(&r_bloom, 0);
4068 Cvar_SetValueQuick(&r_motionblur, 0);
4069 Cvar_SetValueQuick(&r_damageblur, 0);
4072 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
4073 screentexturewidth = screentextureheight = 0;
4074 if (!r_hdr.integer && !r_bloom.integer)
4075 bloomtexturewidth = bloomtextureheight = 0;
4077 // allocate textures as needed
4078 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4080 if (r_bloomstate.texture_screen)
4081 R_FreeTexture(r_bloomstate.texture_screen);
4082 r_bloomstate.texture_screen = NULL;
4083 r_bloomstate.screentexturewidth = screentexturewidth;
4084 r_bloomstate.screentextureheight = screentextureheight;
4085 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4086 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
4088 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4090 if (r_bloomstate.texture_bloom)
4091 R_FreeTexture(r_bloomstate.texture_bloom);
4092 r_bloomstate.texture_bloom = NULL;
4093 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4094 r_bloomstate.bloomtextureheight = bloomtextureheight;
4095 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4096 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
4099 // when doing a reduced render (HDR) we want to use a smaller area
4100 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4101 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4102 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4103 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4104 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4106 // set up a texcoord array for the full resolution screen image
4107 // (we have to keep this around to copy back during final render)
4108 r_bloomstate.screentexcoord2f[0] = 0;
4109 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4110 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4111 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4112 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4113 r_bloomstate.screentexcoord2f[5] = 0;
4114 r_bloomstate.screentexcoord2f[6] = 0;
4115 r_bloomstate.screentexcoord2f[7] = 0;
4117 // set up a texcoord array for the reduced resolution bloom image
4118 // (which will be additive blended over the screen image)
4119 r_bloomstate.bloomtexcoord2f[0] = 0;
4120 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4121 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4122 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4123 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4124 r_bloomstate.bloomtexcoord2f[5] = 0;
4125 r_bloomstate.bloomtexcoord2f[6] = 0;
4126 r_bloomstate.bloomtexcoord2f[7] = 0;
4128 if (r_hdr.integer || r_bloom.integer)
4130 r_bloomstate.enabled = true;
4131 r_bloomstate.hdr = r_hdr.integer != 0;
4134 R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
4137 void R_Bloom_CopyBloomTexture(float colorscale)
4139 r_refdef.stats.bloom++;
4141 // scale down screen texture to the bloom texture size
4143 R_SetViewport(&r_bloomstate.viewport);
4144 GL_BlendFunc(GL_ONE, GL_ZERO);
4145 GL_Color(colorscale, colorscale, colorscale, 1);
4146 // TODO: optimize with multitexture or GLSL
4147 R_SetupGenericShader(true);
4148 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4149 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4150 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 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, polygonelement3i, polygonelement3s, 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, polygonelement3i, polygonelement3s, 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, polygonelement3i, polygonelement3s, 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, polygonelement3i, polygonelement3s, 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, polygonelement3i, polygonelement3s, 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, polygonelement3i, polygonelement3s, 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, polygonelement3i, polygonelement3s, 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, polygonelement3i, polygonelement3s, 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, polygonelement3i, polygonelement3s, 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, polygonelement3i, polygonelement3s, 0, 0);
4536 matrix4x4_t r_waterscrollmatrix;
4538 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4540 if (r_refdef.fog_density)
4542 r_refdef.fogcolor[0] = r_refdef.fog_red;
4543 r_refdef.fogcolor[1] = r_refdef.fog_green;
4544 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4548 VectorCopy(r_refdef.fogcolor, fogvec);
4549 // color.rgb *= ContrastBoost * SceneBrightness;
4550 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4551 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4552 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4553 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4558 void R_UpdateVariables(void)
4562 r_refdef.scene.ambient = r_ambient.value;
4564 r_refdef.farclip = 4096;
4565 if (r_refdef.scene.worldmodel)
4566 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4567 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4569 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4570 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4571 r_refdef.polygonfactor = 0;
4572 r_refdef.polygonoffset = 0;
4573 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4574 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4576 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4577 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4578 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4579 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4580 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4581 if (r_showsurfaces.integer)
4583 r_refdef.scene.rtworld = false;
4584 r_refdef.scene.rtworldshadows = false;
4585 r_refdef.scene.rtdlight = false;
4586 r_refdef.scene.rtdlightshadows = false;
4587 r_refdef.lightmapintensity = 0;
4590 if (gamemode == GAME_NEHAHRA)
4592 if (gl_fogenable.integer)
4594 r_refdef.oldgl_fogenable = true;
4595 r_refdef.fog_density = gl_fogdensity.value;
4596 r_refdef.fog_red = gl_fogred.value;
4597 r_refdef.fog_green = gl_foggreen.value;
4598 r_refdef.fog_blue = gl_fogblue.value;
4599 r_refdef.fog_alpha = 1;
4600 r_refdef.fog_start = 0;
4601 r_refdef.fog_end = gl_skyclip.value;
4603 else if (r_refdef.oldgl_fogenable)
4605 r_refdef.oldgl_fogenable = false;
4606 r_refdef.fog_density = 0;
4607 r_refdef.fog_red = 0;
4608 r_refdef.fog_green = 0;
4609 r_refdef.fog_blue = 0;
4610 r_refdef.fog_alpha = 0;
4611 r_refdef.fog_start = 0;
4612 r_refdef.fog_end = 0;
4616 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4617 r_refdef.fog_start = max(0, r_refdef.fog_start);
4618 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4620 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4622 if (r_refdef.fog_density && r_drawfog.integer)
4624 r_refdef.fogenabled = true;
4625 // this is the point where the fog reaches 0.9986 alpha, which we
4626 // consider a good enough cutoff point for the texture
4627 // (0.9986 * 256 == 255.6)
4628 if (r_fog_exp2.integer)
4629 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4631 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4632 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4633 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4634 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4635 // fog color was already set
4636 // update the fog texture
4637 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
4638 R_BuildFogTexture();
4641 r_refdef.fogenabled = false;
4643 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4645 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4647 // build GLSL gamma texture
4648 #define RAMPWIDTH 256
4649 unsigned short ramp[RAMPWIDTH * 3];
4650 unsigned char rampbgr[RAMPWIDTH][4];
4653 r_texture_gammaramps_serial = vid_gammatables_serial;
4655 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4656 for(i = 0; i < RAMPWIDTH; ++i)
4658 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4659 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4660 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4663 if (r_texture_gammaramps)
4665 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4669 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
4675 // remove GLSL gamma texture
4679 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4680 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4686 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4687 if( scenetype != r_currentscenetype ) {
4688 // store the old scenetype
4689 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4690 r_currentscenetype = scenetype;
4691 // move in the new scene
4692 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4701 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4703 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4704 if( scenetype == r_currentscenetype ) {
4705 return &r_refdef.scene;
4707 return &r_scenes_store[ scenetype ];
4716 void R_RenderView(void)
4718 if (r_timereport_active)
4719 R_TimeReport("start");
4720 r_frame++; // used only by R_GetCurrentTexture
4721 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4723 R_AnimCache_NewFrame();
4725 if (r_refdef.view.isoverlay)
4727 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4728 GL_Clear( GL_DEPTH_BUFFER_BIT );
4729 R_TimeReport("depthclear");
4731 r_refdef.view.showdebug = false;
4733 r_waterstate.enabled = false;
4734 r_waterstate.numwaterplanes = 0;
4742 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4743 return; //Host_Error ("R_RenderView: NULL worldmodel");
4745 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4747 // break apart the view matrix into vectors for various purposes
4748 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4749 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4750 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4751 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4752 // make an inverted copy of the view matrix for tracking sprites
4753 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4755 R_Shadow_UpdateWorldLightSelection();
4757 R_Bloom_StartFrame();
4758 R_Water_StartFrame();
4761 if (r_timereport_active)
4762 R_TimeReport("viewsetup");
4764 R_ResetViewRendering3D();
4766 if (r_refdef.view.clear || r_refdef.fogenabled)
4768 R_ClearScreen(r_refdef.fogenabled);
4769 if (r_timereport_active)
4770 R_TimeReport("viewclear");
4772 r_refdef.view.clear = true;
4774 // this produces a bloom texture to be used in R_BlendView() later
4776 R_HDR_RenderBloomTexture();
4778 r_refdef.view.showdebug = true;
4781 if (r_timereport_active)
4782 R_TimeReport("visibility");
4784 r_waterstate.numwaterplanes = 0;
4785 if (r_waterstate.enabled)
4786 R_RenderWaterPlanes();
4789 r_waterstate.numwaterplanes = 0;
4792 if (r_timereport_active)
4793 R_TimeReport("blendview");
4795 GL_Scissor(0, 0, vid.width, vid.height);
4796 GL_ScissorTest(false);
4800 void R_RenderWaterPlanes(void)
4802 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4804 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4805 if (r_timereport_active)
4806 R_TimeReport("waterworld");
4809 // don't let sound skip if going slow
4810 if (r_refdef.scene.extraupdate)
4813 R_DrawModelsAddWaterPlanes();
4814 if (r_timereport_active)
4815 R_TimeReport("watermodels");
4817 if (r_waterstate.numwaterplanes)
4819 R_Water_ProcessPlanes();
4820 if (r_timereport_active)
4821 R_TimeReport("waterscenes");
4825 extern void R_DrawLightningBeams (void);
4826 extern void VM_CL_AddPolygonsToMeshQueue (void);
4827 extern void R_DrawPortals (void);
4828 extern cvar_t cl_locs_show;
4829 static void R_DrawLocs(void);
4830 static void R_DrawEntityBBoxes(void);
4831 void R_RenderScene(void)
4833 r_refdef.stats.renders++;
4837 // don't let sound skip if going slow
4838 if (r_refdef.scene.extraupdate)
4841 R_MeshQueue_BeginScene();
4845 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
4847 if (cl.csqc_vidvars.drawworld)
4849 // don't let sound skip if going slow
4850 if (r_refdef.scene.extraupdate)
4853 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4855 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4856 if (r_timereport_active)
4857 R_TimeReport("worldsky");
4860 if (R_DrawBrushModelsSky() && r_timereport_active)
4861 R_TimeReport("bmodelsky");
4863 if (skyrendermasked && skyrenderlater)
4865 // we have to force off the water clipping plane while rendering sky
4872 R_AnimCache_CacheVisibleEntities();
4874 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4876 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4877 if (r_timereport_active)
4878 R_TimeReport("worlddepth");
4880 if (r_depthfirst.integer >= 2)
4882 R_DrawModelsDepth();
4883 if (r_timereport_active)
4884 R_TimeReport("modeldepth");
4887 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4889 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4890 if (r_timereport_active)
4891 R_TimeReport("world");
4894 // don't let sound skip if going slow
4895 if (r_refdef.scene.extraupdate)
4899 if (r_timereport_active)
4900 R_TimeReport("models");
4902 // don't let sound skip if going slow
4903 if (r_refdef.scene.extraupdate)
4906 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4908 R_DrawModelShadows();
4909 R_ResetViewRendering3D();
4910 // don't let sound skip if going slow
4911 if (r_refdef.scene.extraupdate)
4915 R_ShadowVolumeLighting(false);
4916 if (r_timereport_active)
4917 R_TimeReport("rtlights");
4919 // don't let sound skip if going slow
4920 if (r_refdef.scene.extraupdate)
4923 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4925 R_DrawModelShadows();
4926 R_ResetViewRendering3D();
4927 // don't let sound skip if going slow
4928 if (r_refdef.scene.extraupdate)
4932 if (cl.csqc_vidvars.drawworld)
4934 R_DrawLightningBeams();
4935 if (r_timereport_active)
4936 R_TimeReport("lightning");
4939 if (r_timereport_active)
4940 R_TimeReport("decals");
4943 if (r_timereport_active)
4944 R_TimeReport("particles");
4947 if (r_timereport_active)
4948 R_TimeReport("explosions");
4951 R_SetupGenericShader(true);
4952 VM_CL_AddPolygonsToMeshQueue();
4954 if (r_refdef.view.showdebug)
4956 if (cl_locs_show.integer)
4959 if (r_timereport_active)
4960 R_TimeReport("showlocs");
4963 if (r_drawportals.integer)
4966 if (r_timereport_active)
4967 R_TimeReport("portals");
4970 if (r_showbboxes.value > 0)
4972 R_DrawEntityBBoxes();
4973 if (r_timereport_active)
4974 R_TimeReport("bboxes");
4978 R_SetupGenericShader(true);
4979 R_MeshQueue_RenderTransparent();
4980 if (r_timereport_active)
4981 R_TimeReport("drawtrans");
4983 R_SetupGenericShader(true);
4985 if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0))
4987 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4988 if (r_timereport_active)
4989 R_TimeReport("worlddebug");
4990 R_DrawModelsDebug();
4991 if (r_timereport_active)
4992 R_TimeReport("modeldebug");
4995 R_SetupGenericShader(true);
4997 if (cl.csqc_vidvars.drawworld)
5000 if (r_timereport_active)
5001 R_TimeReport("coronas");
5004 // don't let sound skip if going slow
5005 if (r_refdef.scene.extraupdate)
5008 R_ResetViewRendering2D();
5011 static const unsigned short bboxelements[36] =
5021 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5024 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5025 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5026 GL_DepthMask(false);
5027 GL_DepthRange(0, 1);
5028 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5029 R_Mesh_Matrix(&identitymatrix);
5030 R_Mesh_ResetTextureState();
5032 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5033 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5034 rsurface.fograngerecip = r_refdef.fograngerecip;
5036 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5037 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5038 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5039 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5040 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5041 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5042 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5043 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5044 R_FillColors(color4f, 8, cr, cg, cb, ca);
5045 if (r_refdef.fogenabled)
5047 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5049 f1 = RSurf_FogVertex(v);
5051 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5052 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5053 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5056 R_Mesh_VertexPointer(vertex3f, 0, 0);
5057 R_Mesh_ColorPointer(color4f, 0, 0);
5058 R_Mesh_ResetTextureState();
5059 R_SetupGenericShader(false);
5060 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5063 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5067 prvm_edict_t *edict;
5068 prvm_prog_t *prog_save = prog;
5070 // this function draws bounding boxes of server entities
5074 GL_CullFace(GL_NONE);
5075 R_SetupGenericShader(false);
5079 for (i = 0;i < numsurfaces;i++)
5081 edict = PRVM_EDICT_NUM(surfacelist[i]);
5082 switch ((int)edict->fields.server->solid)
5084 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5085 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5086 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5087 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5088 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5089 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5091 color[3] *= r_showbboxes.value;
5092 color[3] = bound(0, color[3], 1);
5093 GL_DepthTest(!r_showdisabledepthtest.integer);
5094 GL_CullFace(r_refdef.view.cullface_front);
5095 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5101 static void R_DrawEntityBBoxes(void)
5104 prvm_edict_t *edict;
5106 prvm_prog_t *prog_save = prog;
5108 // this function draws bounding boxes of server entities
5114 for (i = 0;i < prog->num_edicts;i++)
5116 edict = PRVM_EDICT_NUM(i);
5117 if (edict->priv.server->free)
5119 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5120 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5122 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5124 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5125 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5131 static const int nomodelelement3i[24] =
5143 static const unsigned short nomodelelement3s[24] =
5155 static const float nomodelvertex3f[6*3] =
5165 static const float nomodelcolor4f[6*4] =
5167 0.0f, 0.0f, 0.5f, 1.0f,
5168 0.0f, 0.0f, 0.5f, 1.0f,
5169 0.0f, 0.5f, 0.0f, 1.0f,
5170 0.0f, 0.5f, 0.0f, 1.0f,
5171 0.5f, 0.0f, 0.0f, 1.0f,
5172 0.5f, 0.0f, 0.0f, 1.0f
5175 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5181 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5182 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5183 rsurface.fograngerecip = r_refdef.fograngerecip;
5185 // this is only called once per entity so numsurfaces is always 1, and
5186 // surfacelist is always {0}, so this code does not handle batches
5187 R_Mesh_Matrix(&ent->matrix);
5189 if (rsurface.ent_flags & RENDER_ADDITIVE)
5191 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5192 GL_DepthMask(false);
5194 else if (ent->alpha < 1)
5196 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5197 GL_DepthMask(false);
5201 GL_BlendFunc(GL_ONE, GL_ZERO);
5204 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5205 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5206 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
5207 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5208 R_SetupGenericShader(false);
5209 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
5210 if (r_refdef.fogenabled)
5213 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5214 R_Mesh_ColorPointer(color4f, 0, 0);
5215 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5216 f1 = RSurf_FogVertex(org);
5218 for (i = 0, c = color4f;i < 6;i++, c += 4)
5220 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5221 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5222 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5226 else if (ent->alpha != 1)
5228 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5229 R_Mesh_ColorPointer(color4f, 0, 0);
5230 for (i = 0, c = color4f;i < 6;i++, c += 4)
5234 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
5235 R_Mesh_ResetTextureState();
5236 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5239 void R_DrawNoModel(entity_render_t *ent)
5242 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5243 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5244 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5246 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5249 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5251 vec3_t right1, right2, diff, normal;
5253 VectorSubtract (org2, org1, normal);
5255 // calculate 'right' vector for start
5256 VectorSubtract (r_refdef.view.origin, org1, diff);
5257 CrossProduct (normal, diff, right1);
5258 VectorNormalize (right1);
5260 // calculate 'right' vector for end
5261 VectorSubtract (r_refdef.view.origin, org2, diff);
5262 CrossProduct (normal, diff, right2);
5263 VectorNormalize (right2);
5265 vert[ 0] = org1[0] + width * right1[0];
5266 vert[ 1] = org1[1] + width * right1[1];
5267 vert[ 2] = org1[2] + width * right1[2];
5268 vert[ 3] = org1[0] - width * right1[0];
5269 vert[ 4] = org1[1] - width * right1[1];
5270 vert[ 5] = org1[2] - width * right1[2];
5271 vert[ 6] = org2[0] - width * right2[0];
5272 vert[ 7] = org2[1] - width * right2[1];
5273 vert[ 8] = org2[2] - width * right2[2];
5274 vert[ 9] = org2[0] + width * right2[0];
5275 vert[10] = org2[1] + width * right2[1];
5276 vert[11] = org2[2] + width * right2[2];
5279 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5281 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)
5283 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
5287 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5288 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5289 rsurface.fograngerecip = r_refdef.fograngerecip;
5291 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
5292 fog = RSurf_FogVertex(origin);
5294 R_Mesh_Matrix(&identitymatrix);
5295 GL_BlendFunc(blendfunc1, blendfunc2);
5297 GL_CullFace(GL_NONE);
5299 GL_DepthMask(false);
5300 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5301 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5302 GL_DepthTest(!depthdisable);
5304 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5305 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5306 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5307 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5308 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5309 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5310 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5311 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5312 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5313 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5314 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5315 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5317 R_Mesh_VertexPointer(vertex3f, 0, 0);
5318 R_Mesh_ColorPointer(NULL, 0, 0);
5319 R_Mesh_ResetTextureState();
5320 R_SetupGenericShader(true);
5321 R_Mesh_TexBind(0, R_GetTexture(texture));
5322 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5323 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5324 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5325 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5327 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5329 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5330 GL_BlendFunc(blendfunc1, GL_ONE);
5332 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5333 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5337 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5342 VectorSet(v, x, y, z);
5343 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5344 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5346 if (i == mesh->numvertices)
5348 if (mesh->numvertices < mesh->maxvertices)
5350 VectorCopy(v, vertex3f);
5351 mesh->numvertices++;
5353 return mesh->numvertices;
5359 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5363 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5364 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5365 e = mesh->element3i + mesh->numtriangles * 3;
5366 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5368 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5369 if (mesh->numtriangles < mesh->maxtriangles)
5374 mesh->numtriangles++;
5376 element[1] = element[2];
5380 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5384 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5385 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5386 e = mesh->element3i + mesh->numtriangles * 3;
5387 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5389 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5390 if (mesh->numtriangles < mesh->maxtriangles)
5395 mesh->numtriangles++;
5397 element[1] = element[2];
5401 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5402 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5404 int planenum, planenum2;
5407 mplane_t *plane, *plane2;
5409 double temppoints[2][256*3];
5410 // figure out how large a bounding box we need to properly compute this brush
5412 for (w = 0;w < numplanes;w++)
5413 maxdist = max(maxdist, fabs(planes[w].dist));
5414 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5415 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5416 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5420 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5421 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5423 if (planenum2 == planenum)
5425 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);
5428 if (tempnumpoints < 3)
5430 // generate elements forming a triangle fan for this polygon
5431 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5435 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)
5437 texturelayer_t *layer;
5438 layer = t->currentlayers + t->currentnumlayers++;
5440 layer->depthmask = depthmask;
5441 layer->blendfunc1 = blendfunc1;
5442 layer->blendfunc2 = blendfunc2;
5443 layer->texture = texture;
5444 layer->texmatrix = *matrix;
5445 layer->color[0] = r * r_refdef.view.colorscale;
5446 layer->color[1] = g * r_refdef.view.colorscale;
5447 layer->color[2] = b * r_refdef.view.colorscale;
5448 layer->color[3] = a;
5451 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5454 index = parms[2] + r_refdef.scene.time * parms[3];
5455 index -= floor(index);
5459 case Q3WAVEFUNC_NONE:
5460 case Q3WAVEFUNC_NOISE:
5461 case Q3WAVEFUNC_COUNT:
5464 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5465 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5466 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5467 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5468 case Q3WAVEFUNC_TRIANGLE:
5470 f = index - floor(index);
5481 return (float)(parms[0] + parms[1] * f);
5484 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5489 matrix4x4_t matrix, temp;
5490 switch(tcmod->tcmod)
5494 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5495 matrix = r_waterscrollmatrix;
5497 matrix = identitymatrix;
5499 case Q3TCMOD_ENTITYTRANSLATE:
5500 // this is used in Q3 to allow the gamecode to control texcoord
5501 // scrolling on the entity, which is not supported in darkplaces yet.
5502 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5504 case Q3TCMOD_ROTATE:
5505 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5506 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5507 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5510 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5512 case Q3TCMOD_SCROLL:
5513 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5515 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5516 w = (int) tcmod->parms[0];
5517 h = (int) tcmod->parms[1];
5518 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5520 idx = (int) floor(f * w * h);
5521 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5523 case Q3TCMOD_STRETCH:
5524 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5525 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5527 case Q3TCMOD_TRANSFORM:
5528 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5529 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5530 VectorSet(tcmat + 6, 0 , 0 , 1);
5531 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5532 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5534 case Q3TCMOD_TURBULENT:
5535 // this is handled in the RSurf_PrepareVertices function
5536 matrix = identitymatrix;
5540 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5543 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5545 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5546 char name[MAX_QPATH];
5547 skinframe_t *skinframe;
5548 unsigned char pixels[296*194];
5549 strlcpy(cache->name, skinname, sizeof(cache->name));
5550 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5551 if (developer_loading.integer)
5552 Con_Printf("loading %s\n", name);
5553 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5554 if (!skinframe || !skinframe->base)
5557 fs_offset_t filesize;
5559 f = FS_LoadFile(name, tempmempool, true, &filesize);
5562 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5563 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5567 cache->skinframe = skinframe;
5570 texture_t *R_GetCurrentTexture(texture_t *t)
5573 const entity_render_t *ent = rsurface.entity;
5574 dp_model_t *model = ent->model;
5575 q3shaderinfo_layer_tcmod_t *tcmod;
5577 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5578 return t->currentframe;
5579 t->update_lastrenderframe = r_frame;
5580 t->update_lastrenderentity = (void *)ent;
5582 // switch to an alternate material if this is a q1bsp animated material
5584 texture_t *texture = t;
5585 int s = rsurface.ent_skinnum;
5586 if ((unsigned int)s >= (unsigned int)model->numskins)
5588 if (model->skinscenes)
5590 if (model->skinscenes[s].framecount > 1)
5591 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5593 s = model->skinscenes[s].firstframe;
5596 t = t + s * model->num_surfaces;
5599 // use an alternate animation if the entity's frame is not 0,
5600 // and only if the texture has an alternate animation
5601 if (rsurface.frameblend[0].subframe != 0 && t->anim_total[1])
5602 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5604 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5606 texture->currentframe = t;
5609 // update currentskinframe to be a qw skin or animation frame
5610 if (rsurface.ent_qwskin >= 0)
5612 i = rsurface.ent_qwskin;
5613 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5615 r_qwskincache_size = cl.maxclients;
5617 Mem_Free(r_qwskincache);
5618 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5620 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5621 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5622 t->currentskinframe = r_qwskincache[i].skinframe;
5623 if (t->currentskinframe == NULL)
5624 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5626 else if (t->numskinframes >= 2)
5627 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5628 if (t->backgroundnumskinframes >= 2)
5629 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5631 t->currentmaterialflags = t->basematerialflags;
5632 t->currentalpha = rsurface.ent_color[3];
5633 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5634 t->currentalpha *= r_wateralpha.value;
5635 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5636 t->currentalpha *= t->r_water_wateralpha;
5637 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5638 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5639 if (!(rsurface.ent_flags & RENDER_LIGHT))
5640 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5641 else if (rsurface.modeltexcoordlightmap2f == NULL)
5643 // pick a model lighting mode
5644 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5645 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5647 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5649 if (rsurface.ent_flags & RENDER_ADDITIVE)
5650 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5651 else if (t->currentalpha < 1)
5652 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5653 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5654 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5655 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5656 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5657 if (t->backgroundnumskinframes)
5658 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5659 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5661 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5662 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5665 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5667 // there is no tcmod
5668 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5670 t->currenttexmatrix = r_waterscrollmatrix;
5671 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5675 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5676 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5679 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5680 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5681 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5682 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5684 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5685 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5686 t->glosstexture = r_texture_black;
5687 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5688 t->backgroundglosstexture = r_texture_black;
5689 t->specularpower = r_shadow_glossexponent.value;
5690 // TODO: store reference values for these in the texture?
5691 t->specularscale = 0;
5692 if (r_shadow_gloss.integer > 0)
5694 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5696 if (r_shadow_glossintensity.value > 0)
5698 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5699 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5700 t->specularscale = r_shadow_glossintensity.value;
5703 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5705 t->glosstexture = r_texture_white;
5706 t->backgroundglosstexture = r_texture_white;
5707 t->specularscale = r_shadow_gloss2intensity.value;
5708 t->specularpower = r_shadow_gloss2exponent.value;
5711 t->specularscale *= t->specularscalemod;
5712 t->specularpower *= t->specularpowermod;
5714 // lightmaps mode looks bad with dlights using actual texturing, so turn
5715 // off the colormap and glossmap, but leave the normalmap on as it still
5716 // accurately represents the shading involved
5717 if (gl_lightmaps.integer)
5719 t->basetexture = r_texture_grey128;
5720 t->backgroundbasetexture = NULL;
5721 t->specularscale = 0;
5722 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5725 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5726 VectorClear(t->dlightcolor);
5727 t->currentnumlayers = 0;
5728 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5731 int blendfunc1, blendfunc2;
5733 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5735 blendfunc1 = GL_SRC_ALPHA;
5736 blendfunc2 = GL_ONE;
5738 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5740 blendfunc1 = GL_SRC_ALPHA;
5741 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5743 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5745 blendfunc1 = t->customblendfunc[0];
5746 blendfunc2 = t->customblendfunc[1];
5750 blendfunc1 = GL_ONE;
5751 blendfunc2 = GL_ZERO;
5753 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5754 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5755 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5756 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5758 // fullbright is not affected by r_refdef.lightmapintensity
5759 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]);
5760 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5761 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5762 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5763 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5767 vec3_t ambientcolor;
5769 // set the color tint used for lights affecting this surface
5770 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5772 // q3bsp has no lightmap updates, so the lightstylevalue that
5773 // would normally be baked into the lightmap must be
5774 // applied to the color
5775 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5776 if (model->type == mod_brushq3)
5777 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5778 colorscale *= r_refdef.lightmapintensity;
5779 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5780 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5781 // basic lit geometry
5782 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]);
5783 // add pants/shirt if needed
5784 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5785 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5786 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5787 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5788 // now add ambient passes if needed
5789 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5791 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]);
5792 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5793 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
5794 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5795 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
5798 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5799 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]);
5800 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5802 // if this is opaque use alpha blend which will darken the earlier
5805 // if this is an alpha blended material, all the earlier passes
5806 // were darkened by fog already, so we only need to add the fog
5807 // color ontop through the fog mask texture
5809 // if this is an additive blended material, all the earlier passes
5810 // were darkened by fog already, and we should not add fog color
5811 // (because the background was not darkened, there is no fog color
5812 // that was lost behind it).
5813 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]);
5817 return t->currentframe;
5820 rsurfacestate_t rsurface;
5822 void R_Mesh_ResizeArrays(int newvertices)
5825 if (rsurface.array_size >= newvertices)
5827 if (rsurface.array_modelvertex3f)
5828 Mem_Free(rsurface.array_modelvertex3f);
5829 rsurface.array_size = (newvertices + 1023) & ~1023;
5830 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5831 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5832 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5833 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5834 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5835 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5836 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5837 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5838 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5839 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5840 rsurface.array_color4f = base + rsurface.array_size * 27;
5841 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5844 void RSurf_ActiveWorldEntity(void)
5846 dp_model_t *model = r_refdef.scene.worldmodel;
5847 //if (rsurface.entity == r_refdef.scene.worldentity)
5849 rsurface.entity = r_refdef.scene.worldentity;
5850 rsurface.ent_skinnum = 0;
5851 rsurface.ent_qwskin = -1;
5852 rsurface.ent_shadertime = 0;
5853 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
5854 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
5855 if (rsurface.array_size < model->surfmesh.num_vertices)
5856 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5857 rsurface.matrix = identitymatrix;
5858 rsurface.inversematrix = identitymatrix;
5859 rsurface.matrixscale = 1;
5860 rsurface.inversematrixscale = 1;
5861 R_Mesh_Matrix(&identitymatrix);
5862 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5863 rsurface.fograngerecip = r_refdef.fograngerecip;
5864 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
5865 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5866 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5867 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5868 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5869 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5870 VectorSet(rsurface.glowmod, 1, 1, 1);
5871 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5872 rsurface.frameblend[0].lerp = 1;
5873 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5874 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5875 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5876 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5877 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5878 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5879 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5880 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5881 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5882 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5883 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5884 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5885 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5886 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5887 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5888 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5889 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5890 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5891 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5892 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5893 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5894 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5895 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5896 rsurface.modelelement3i = model->surfmesh.data_element3i;
5897 rsurface.modelelement3s = model->surfmesh.data_element3s;
5898 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5899 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5900 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5901 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5902 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5903 rsurface.modelsurfaces = model->data_surfaces;
5904 rsurface.generatedvertex = false;
5905 rsurface.vertex3f = rsurface.modelvertex3f;
5906 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5907 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5908 rsurface.svector3f = rsurface.modelsvector3f;
5909 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5910 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5911 rsurface.tvector3f = rsurface.modeltvector3f;
5912 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5913 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5914 rsurface.normal3f = rsurface.modelnormal3f;
5915 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5916 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5917 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5920 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5922 dp_model_t *model = ent->model;
5923 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5925 rsurface.entity = (entity_render_t *)ent;
5926 rsurface.ent_skinnum = ent->skinnum;
5927 rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
5928 rsurface.ent_shadertime = ent->shadertime;
5929 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
5930 rsurface.ent_flags = ent->flags;
5931 if (rsurface.array_size < model->surfmesh.num_vertices)
5932 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5933 rsurface.matrix = ent->matrix;
5934 rsurface.inversematrix = ent->inversematrix;
5935 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
5936 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
5937 R_Mesh_Matrix(&rsurface.matrix);
5938 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
5939 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
5940 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
5941 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
5942 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5943 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5944 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5945 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5946 VectorCopy(ent->glowmod, rsurface.glowmod);
5947 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5948 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5949 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5950 if (ent->model->brush.submodel)
5952 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5953 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5955 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5957 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5959 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5960 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5961 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5962 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5964 else if (wanttangents)
5966 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5967 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5968 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5969 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5970 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5972 else if (wantnormals)
5974 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5975 rsurface.modelsvector3f = NULL;
5976 rsurface.modeltvector3f = NULL;
5977 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5978 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5982 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5983 rsurface.modelsvector3f = NULL;
5984 rsurface.modeltvector3f = NULL;
5985 rsurface.modelnormal3f = NULL;
5986 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5988 rsurface.modelvertex3f_bufferobject = 0;
5989 rsurface.modelvertex3f_bufferoffset = 0;
5990 rsurface.modelsvector3f_bufferobject = 0;
5991 rsurface.modelsvector3f_bufferoffset = 0;
5992 rsurface.modeltvector3f_bufferobject = 0;
5993 rsurface.modeltvector3f_bufferoffset = 0;
5994 rsurface.modelnormal3f_bufferobject = 0;
5995 rsurface.modelnormal3f_bufferoffset = 0;
5996 rsurface.generatedvertex = true;
6000 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6001 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6002 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6003 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6004 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6005 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6006 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6007 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6008 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6009 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6010 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6011 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6012 rsurface.generatedvertex = false;
6014 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6015 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6016 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6017 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6018 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6019 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6020 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6021 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6022 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6023 rsurface.modelelement3i = model->surfmesh.data_element3i;
6024 rsurface.modelelement3s = model->surfmesh.data_element3s;
6025 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6026 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6027 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6028 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6029 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6030 rsurface.modelsurfaces = model->data_surfaces;
6031 rsurface.vertex3f = rsurface.modelvertex3f;
6032 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6033 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6034 rsurface.svector3f = rsurface.modelsvector3f;
6035 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6036 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6037 rsurface.tvector3f = rsurface.modeltvector3f;
6038 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6039 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6040 rsurface.normal3f = rsurface.modelnormal3f;
6041 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6042 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6043 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6046 float RSurf_FogPoint(const float *v)
6048 float len = VectorDistance(r_refdef.view.origin, v);
6049 unsigned int fogmasktableindex;
6050 fogmasktableindex = (unsigned int)(len * r_refdef.fogmasktabledistmultiplier);
6051 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6054 float RSurf_FogVertex(const float *v)
6056 float len = VectorDistance(rsurface.localvieworigin, v);
6057 unsigned int fogmasktableindex;
6058 fogmasktableindex = (unsigned int)(len * rsurface.fogmasktabledistmultiplier);
6059 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6062 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6063 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
6066 int texturesurfaceindex;
6071 const float *v1, *in_tc;
6073 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6075 q3shaderinfo_deform_t *deform;
6076 // 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
6077 if (rsurface.generatedvertex)
6079 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6080 generatenormals = true;
6081 for (i = 0;i < Q3MAXDEFORMS;i++)
6083 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6085 generatetangents = true;
6086 generatenormals = true;
6088 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6089 generatenormals = true;
6091 if (generatenormals && !rsurface.modelnormal3f)
6093 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6094 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6095 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6096 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6098 if (generatetangents && !rsurface.modelsvector3f)
6100 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6101 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6102 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6103 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6104 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6105 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6106 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);
6109 rsurface.vertex3f = rsurface.modelvertex3f;
6110 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6111 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6112 rsurface.svector3f = rsurface.modelsvector3f;
6113 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6114 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6115 rsurface.tvector3f = rsurface.modeltvector3f;
6116 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6117 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6118 rsurface.normal3f = rsurface.modelnormal3f;
6119 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6120 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6121 // if vertices are deformed (sprite flares and things in maps, possibly
6122 // water waves, bulges and other deformations), generate them into
6123 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6124 // (may be static model data or generated data for an animated model, or
6125 // the previous deform pass)
6126 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6128 switch (deform->deform)
6131 case Q3DEFORM_PROJECTIONSHADOW:
6132 case Q3DEFORM_TEXT0:
6133 case Q3DEFORM_TEXT1:
6134 case Q3DEFORM_TEXT2:
6135 case Q3DEFORM_TEXT3:
6136 case Q3DEFORM_TEXT4:
6137 case Q3DEFORM_TEXT5:
6138 case Q3DEFORM_TEXT6:
6139 case Q3DEFORM_TEXT7:
6142 case Q3DEFORM_AUTOSPRITE:
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 // a single autosprite surface can contain multiple sprites...
6154 for (j = 0;j < surface->num_vertices - 3;j += 4)
6156 VectorClear(center);
6157 for (i = 0;i < 4;i++)
6158 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6159 VectorScale(center, 0.25f, center);
6160 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6161 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6162 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6163 for (i = 0;i < 4;i++)
6165 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6166 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6169 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);
6170 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);
6172 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6173 rsurface.vertex3f_bufferobject = 0;
6174 rsurface.vertex3f_bufferoffset = 0;
6175 rsurface.svector3f = rsurface.array_deformedsvector3f;
6176 rsurface.svector3f_bufferobject = 0;
6177 rsurface.svector3f_bufferoffset = 0;
6178 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6179 rsurface.tvector3f_bufferobject = 0;
6180 rsurface.tvector3f_bufferoffset = 0;
6181 rsurface.normal3f = rsurface.array_deformednormal3f;
6182 rsurface.normal3f_bufferobject = 0;
6183 rsurface.normal3f_bufferoffset = 0;
6185 case Q3DEFORM_AUTOSPRITE2:
6186 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6187 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6188 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6189 VectorNormalize(newforward);
6190 VectorNormalize(newright);
6191 VectorNormalize(newup);
6192 // make deformed versions of only the model vertices used by the specified surfaces
6193 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6195 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6196 const float *v1, *v2;
6206 memset(shortest, 0, sizeof(shortest));
6207 // a single autosprite surface can contain multiple sprites...
6208 for (j = 0;j < surface->num_vertices - 3;j += 4)
6210 VectorClear(center);
6211 for (i = 0;i < 4;i++)
6212 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6213 VectorScale(center, 0.25f, center);
6214 // find the two shortest edges, then use them to define the
6215 // axis vectors for rotating around the central axis
6216 for (i = 0;i < 6;i++)
6218 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6219 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6221 Debug_PolygonBegin(NULL, 0);
6222 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6223 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);
6224 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6227 l = VectorDistance2(v1, v2);
6228 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6230 l += (1.0f / 1024.0f);
6231 if (shortest[0].length2 > l || i == 0)
6233 shortest[1] = shortest[0];
6234 shortest[0].length2 = l;
6235 shortest[0].v1 = v1;
6236 shortest[0].v2 = v2;
6238 else if (shortest[1].length2 > l || i == 1)
6240 shortest[1].length2 = l;
6241 shortest[1].v1 = v1;
6242 shortest[1].v2 = v2;
6245 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6246 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6248 Debug_PolygonBegin(NULL, 0);
6249 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6250 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);
6251 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6254 // this calculates the right vector from the shortest edge
6255 // and the up vector from the edge midpoints
6256 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6257 VectorNormalize(right);
6258 VectorSubtract(end, start, up);
6259 VectorNormalize(up);
6260 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6261 VectorSubtract(rsurface.localvieworigin, center, forward);
6262 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6263 VectorNegate(forward, forward);
6264 VectorReflect(forward, 0, up, forward);
6265 VectorNormalize(forward);
6266 CrossProduct(up, forward, newright);
6267 VectorNormalize(newright);
6269 Debug_PolygonBegin(NULL, 0);
6270 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);
6271 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6272 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6276 Debug_PolygonBegin(NULL, 0);
6277 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6278 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6279 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6282 // rotate the quad around the up axis vector, this is made
6283 // especially easy by the fact we know the quad is flat,
6284 // so we only have to subtract the center position and
6285 // measure distance along the right vector, and then
6286 // multiply that by the newright vector and add back the
6288 // we also need to subtract the old position to undo the
6289 // displacement from the center, which we do with a
6290 // DotProduct, the subtraction/addition of center is also
6291 // optimized into DotProducts here
6292 l = DotProduct(right, center);
6293 for (i = 0;i < 4;i++)
6295 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6296 f = DotProduct(right, v1) - l;
6297 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6300 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);
6301 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);
6303 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6304 rsurface.vertex3f_bufferobject = 0;
6305 rsurface.vertex3f_bufferoffset = 0;
6306 rsurface.svector3f = rsurface.array_deformedsvector3f;
6307 rsurface.svector3f_bufferobject = 0;
6308 rsurface.svector3f_bufferoffset = 0;
6309 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6310 rsurface.tvector3f_bufferobject = 0;
6311 rsurface.tvector3f_bufferoffset = 0;
6312 rsurface.normal3f = rsurface.array_deformednormal3f;
6313 rsurface.normal3f_bufferobject = 0;
6314 rsurface.normal3f_bufferoffset = 0;
6316 case Q3DEFORM_NORMAL:
6317 // deform the normals to make reflections wavey
6318 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6320 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6321 for (j = 0;j < surface->num_vertices;j++)
6324 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6325 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6326 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6327 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6328 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6329 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6330 VectorNormalize(normal);
6332 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);
6334 rsurface.svector3f = rsurface.array_deformedsvector3f;
6335 rsurface.svector3f_bufferobject = 0;
6336 rsurface.svector3f_bufferoffset = 0;
6337 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6338 rsurface.tvector3f_bufferobject = 0;
6339 rsurface.tvector3f_bufferoffset = 0;
6340 rsurface.normal3f = rsurface.array_deformednormal3f;
6341 rsurface.normal3f_bufferobject = 0;
6342 rsurface.normal3f_bufferoffset = 0;
6345 // deform vertex array to make wavey water and flags and such
6346 waveparms[0] = deform->waveparms[0];
6347 waveparms[1] = deform->waveparms[1];
6348 waveparms[2] = deform->waveparms[2];
6349 waveparms[3] = deform->waveparms[3];
6350 // this is how a divisor of vertex influence on deformation
6351 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6352 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6353 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6355 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6356 for (j = 0;j < surface->num_vertices;j++)
6358 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6359 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6360 // if the wavefunc depends on time, evaluate it per-vertex
6363 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6364 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6366 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6369 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6370 rsurface.vertex3f_bufferobject = 0;
6371 rsurface.vertex3f_bufferoffset = 0;
6373 case Q3DEFORM_BULGE:
6374 // deform vertex array to make the surface have moving bulges
6375 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6377 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6378 for (j = 0;j < surface->num_vertices;j++)
6380 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6381 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6384 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6385 rsurface.vertex3f_bufferobject = 0;
6386 rsurface.vertex3f_bufferoffset = 0;
6389 // deform vertex array
6390 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6391 VectorScale(deform->parms, scale, waveparms);
6392 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6394 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6395 for (j = 0;j < surface->num_vertices;j++)
6396 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6398 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6399 rsurface.vertex3f_bufferobject = 0;
6400 rsurface.vertex3f_bufferoffset = 0;
6404 // generate texcoords based on the chosen texcoord source
6405 switch(rsurface.texture->tcgen.tcgen)
6408 case Q3TCGEN_TEXTURE:
6409 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6410 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6411 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6413 case Q3TCGEN_LIGHTMAP:
6414 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6415 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6416 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6418 case Q3TCGEN_VECTOR:
6419 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6421 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6422 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)
6424 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6425 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6428 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6429 rsurface.texcoordtexture2f_bufferobject = 0;
6430 rsurface.texcoordtexture2f_bufferoffset = 0;
6432 case Q3TCGEN_ENVIRONMENT:
6433 // make environment reflections using a spheremap
6434 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6436 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6437 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6438 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6439 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6440 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6442 // identical to Q3A's method, but executed in worldspace so
6443 // carried models can be shiny too
6445 float viewer[3], d, reflected[3], worldreflected[3];
6447 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6448 // VectorNormalize(viewer);
6450 d = DotProduct(normal, viewer);
6452 reflected[0] = normal[0]*2*d - viewer[0];
6453 reflected[1] = normal[1]*2*d - viewer[1];
6454 reflected[2] = normal[2]*2*d - viewer[2];
6455 // note: this is proportinal to viewer, so we can normalize later
6457 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6458 VectorNormalize(worldreflected);
6460 // note: this sphere map only uses world x and z!
6461 // so positive and negative y will LOOK THE SAME.
6462 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6463 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6466 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6467 rsurface.texcoordtexture2f_bufferobject = 0;
6468 rsurface.texcoordtexture2f_bufferoffset = 0;
6471 // the only tcmod that needs software vertex processing is turbulent, so
6472 // check for it here and apply the changes if needed
6473 // and we only support that as the first one
6474 // (handling a mixture of turbulent and other tcmods would be problematic
6475 // without punting it entirely to a software path)
6476 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6478 amplitude = rsurface.texture->tcmods[0].parms[1];
6479 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6480 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6482 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6483 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)
6485 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6486 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6489 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6490 rsurface.texcoordtexture2f_bufferobject = 0;
6491 rsurface.texcoordtexture2f_bufferoffset = 0;
6493 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6494 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6495 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6496 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6499 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6502 const msurface_t *surface = texturesurfacelist[0];
6503 const msurface_t *surface2;
6508 // TODO: lock all array ranges before render, rather than on each surface
6509 if (texturenumsurfaces == 1)
6511 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6512 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);
6514 else if (r_batchmode.integer == 2)
6516 #define MAXBATCHTRIANGLES 4096
6517 int batchtriangles = 0;
6518 int batchelements[MAXBATCHTRIANGLES*3];
6519 for (i = 0;i < texturenumsurfaces;i = j)
6521 surface = texturesurfacelist[i];
6523 if (surface->num_triangles > MAXBATCHTRIANGLES)
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);
6528 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6529 batchtriangles = surface->num_triangles;
6530 firstvertex = surface->num_firstvertex;
6531 endvertex = surface->num_firstvertex + surface->num_vertices;
6532 for (;j < texturenumsurfaces;j++)
6534 surface2 = texturesurfacelist[j];
6535 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6537 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6538 batchtriangles += surface2->num_triangles;
6539 firstvertex = min(firstvertex, surface2->num_firstvertex);
6540 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6542 surface2 = texturesurfacelist[j-1];
6543 numvertices = endvertex - firstvertex;
6544 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6547 else if (r_batchmode.integer == 1)
6549 for (i = 0;i < texturenumsurfaces;i = j)
6551 surface = texturesurfacelist[i];
6552 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6553 if (texturesurfacelist[j] != surface2)
6555 surface2 = texturesurfacelist[j-1];
6556 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6557 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6558 GL_LockArrays(surface->num_firstvertex, numvertices);
6559 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6564 for (i = 0;i < texturenumsurfaces;i++)
6566 surface = texturesurfacelist[i];
6567 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6568 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);
6573 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6575 int i, planeindex, vertexindex;
6579 r_waterstate_waterplane_t *p, *bestp;
6580 msurface_t *surface;
6581 if (r_waterstate.renderingscene)
6583 for (i = 0;i < texturenumsurfaces;i++)
6585 surface = texturesurfacelist[i];
6586 if (lightmaptexunit >= 0)
6587 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6588 if (deluxemaptexunit >= 0)
6589 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6590 // pick the closest matching water plane
6593 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6596 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6598 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6599 d += fabs(PlaneDiff(vert, &p->plane));
6601 if (bestd > d || !bestp)
6609 if (refractiontexunit >= 0)
6610 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6611 if (reflectiontexunit >= 0)
6612 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6616 if (refractiontexunit >= 0)
6617 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6618 if (reflectiontexunit >= 0)
6619 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6621 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6622 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);
6626 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6630 const msurface_t *surface = texturesurfacelist[0];
6631 const msurface_t *surface2;
6636 // TODO: lock all array ranges before render, rather than on each surface
6637 if (texturenumsurfaces == 1)
6639 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6640 if (deluxemaptexunit >= 0)
6641 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6642 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6643 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);
6645 else if (r_batchmode.integer == 2)
6647 #define MAXBATCHTRIANGLES 4096
6648 int batchtriangles = 0;
6649 int batchelements[MAXBATCHTRIANGLES*3];
6650 for (i = 0;i < texturenumsurfaces;i = j)
6652 surface = texturesurfacelist[i];
6653 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6654 if (deluxemaptexunit >= 0)
6655 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6657 if (surface->num_triangles > MAXBATCHTRIANGLES)
6659 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);
6662 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6663 batchtriangles = surface->num_triangles;
6664 firstvertex = surface->num_firstvertex;
6665 endvertex = surface->num_firstvertex + surface->num_vertices;
6666 for (;j < texturenumsurfaces;j++)
6668 surface2 = texturesurfacelist[j];
6669 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6671 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6672 batchtriangles += surface2->num_triangles;
6673 firstvertex = min(firstvertex, surface2->num_firstvertex);
6674 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6676 surface2 = texturesurfacelist[j-1];
6677 numvertices = endvertex - firstvertex;
6678 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6681 else if (r_batchmode.integer == 1)
6684 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6685 for (i = 0;i < texturenumsurfaces;i = j)
6687 surface = texturesurfacelist[i];
6688 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6689 if (texturesurfacelist[j] != surface2)
6691 Con_Printf(" %i", j - i);
6694 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6696 for (i = 0;i < texturenumsurfaces;i = j)
6698 surface = texturesurfacelist[i];
6699 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6700 if (deluxemaptexunit >= 0)
6701 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6702 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6703 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6706 Con_Printf(" %i", j - i);
6708 surface2 = texturesurfacelist[j-1];
6709 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6710 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6711 GL_LockArrays(surface->num_firstvertex, numvertices);
6712 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6720 for (i = 0;i < texturenumsurfaces;i++)
6722 surface = texturesurfacelist[i];
6723 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6724 if (deluxemaptexunit >= 0)
6725 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6726 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6727 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);
6732 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6735 int texturesurfaceindex;
6736 if (r_showsurfaces.integer == 2)
6738 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6740 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6741 for (j = 0;j < surface->num_triangles;j++)
6743 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6744 GL_Color(f, f, f, 1);
6745 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6751 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6753 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6754 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6755 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);
6756 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6757 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);
6762 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6764 int texturesurfaceindex;
6767 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6769 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6770 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)
6778 rsurface.lightmapcolor4f = rsurface.array_color4f;
6779 rsurface.lightmapcolor4f_bufferobject = 0;
6780 rsurface.lightmapcolor4f_bufferoffset = 0;
6783 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6785 int texturesurfaceindex;
6789 if (rsurface.lightmapcolor4f)
6791 // generate color arrays for the surfaces in this list
6792 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6794 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6795 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)
6797 f = RSurf_FogVertex(v);
6807 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6809 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6810 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)
6812 f = RSurf_FogVertex(v);
6820 rsurface.lightmapcolor4f = rsurface.array_color4f;
6821 rsurface.lightmapcolor4f_bufferobject = 0;
6822 rsurface.lightmapcolor4f_bufferoffset = 0;
6825 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6827 int texturesurfaceindex;
6831 if (!rsurface.lightmapcolor4f)
6833 // generate color arrays for the surfaces in this list
6834 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6836 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6837 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)
6839 f = RSurf_FogVertex(v);
6840 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6841 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6842 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6846 rsurface.lightmapcolor4f = rsurface.array_color4f;
6847 rsurface.lightmapcolor4f_bufferobject = 0;
6848 rsurface.lightmapcolor4f_bufferoffset = 0;
6851 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6853 int texturesurfaceindex;
6856 if (!rsurface.lightmapcolor4f)
6858 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6860 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6861 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)
6869 rsurface.lightmapcolor4f = rsurface.array_color4f;
6870 rsurface.lightmapcolor4f_bufferobject = 0;
6871 rsurface.lightmapcolor4f_bufferoffset = 0;
6874 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6876 int texturesurfaceindex;
6879 if (!rsurface.lightmapcolor4f)
6881 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6883 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6884 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)
6886 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6887 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6888 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6892 rsurface.lightmapcolor4f = rsurface.array_color4f;
6893 rsurface.lightmapcolor4f_bufferobject = 0;
6894 rsurface.lightmapcolor4f_bufferoffset = 0;
6897 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6900 rsurface.lightmapcolor4f = NULL;
6901 rsurface.lightmapcolor4f_bufferobject = 0;
6902 rsurface.lightmapcolor4f_bufferoffset = 0;
6903 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6904 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6905 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6906 GL_Color(r, g, b, a);
6907 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6910 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6912 // TODO: optimize applyfog && applycolor case
6913 // just apply fog if necessary, and tint the fog color array if necessary
6914 rsurface.lightmapcolor4f = NULL;
6915 rsurface.lightmapcolor4f_bufferobject = 0;
6916 rsurface.lightmapcolor4f_bufferoffset = 0;
6917 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6918 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6919 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6920 GL_Color(r, g, b, a);
6921 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6924 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6926 int texturesurfaceindex;
6930 if (texturesurfacelist[0]->lightmapinfo)
6932 // generate color arrays for the surfaces in this list
6933 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6935 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6936 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6938 if (surface->lightmapinfo->samples)
6940 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6941 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6942 VectorScale(lm, scale, c);
6943 if (surface->lightmapinfo->styles[1] != 255)
6945 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6947 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6948 VectorMA(c, scale, lm, c);
6949 if (surface->lightmapinfo->styles[2] != 255)
6952 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6953 VectorMA(c, scale, lm, c);
6954 if (surface->lightmapinfo->styles[3] != 255)
6957 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6958 VectorMA(c, scale, lm, c);
6968 rsurface.lightmapcolor4f = rsurface.array_color4f;
6969 rsurface.lightmapcolor4f_bufferobject = 0;
6970 rsurface.lightmapcolor4f_bufferoffset = 0;
6974 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6975 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6976 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6978 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6979 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6980 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6981 GL_Color(r, g, b, a);
6982 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6985 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6987 int texturesurfaceindex;
6990 float *v, *c, *c2, alpha;
6991 vec3_t ambientcolor;
6992 vec3_t diffusecolor;
6996 VectorCopy(rsurface.modellight_lightdir, lightdir);
6997 f = 0.5f * r_refdef.lightmapintensity;
6998 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6999 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7000 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7001 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7002 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7003 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7005 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7007 // generate color arrays for the surfaces in this list
7008 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7010 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7011 int numverts = surface->num_vertices;
7012 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7013 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
7014 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7015 // q3-style directional shading
7016 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
7018 if ((f = DotProduct(c2, lightdir)) > 0)
7019 VectorMA(ambientcolor, f, diffusecolor, c);
7021 VectorCopy(ambientcolor, c);
7029 rsurface.lightmapcolor4f = rsurface.array_color4f;
7030 rsurface.lightmapcolor4f_bufferobject = 0;
7031 rsurface.lightmapcolor4f_bufferoffset = 0;
7032 *applycolor = false;
7036 *r = ambientcolor[0];
7037 *g = ambientcolor[1];
7038 *b = ambientcolor[2];
7039 rsurface.lightmapcolor4f = NULL;
7040 rsurface.lightmapcolor4f_bufferobject = 0;
7041 rsurface.lightmapcolor4f_bufferoffset = 0;
7045 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7047 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7048 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7049 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7050 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7051 GL_Color(r, g, b, a);
7052 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7055 void RSurf_SetupDepthAndCulling(void)
7057 // submodels are biased to avoid z-fighting with world surfaces that they
7058 // may be exactly overlapping (avoids z-fighting artifacts on certain
7059 // doors and things in Quake maps)
7060 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7061 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7062 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7063 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7066 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
7068 // transparent sky would be ridiculous
7069 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7071 R_SetupGenericShader(false);
7072 skyrenderlater = true;
7073 RSurf_SetupDepthAndCulling();
7075 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7076 // skymasking on them, and Quake3 never did sky masking (unlike
7077 // software Quake and software Quake2), so disable the sky masking
7078 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7079 // and skymasking also looks very bad when noclipping outside the
7080 // level, so don't use it then either.
7081 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7083 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7084 R_Mesh_ColorPointer(NULL, 0, 0);
7085 R_Mesh_ResetTextureState();
7086 if (skyrendermasked)
7088 R_SetupDepthOrShadowShader();
7089 // depth-only (masking)
7090 GL_ColorMask(0,0,0,0);
7091 // just to make sure that braindead drivers don't draw
7092 // anything despite that colormask...
7093 GL_BlendFunc(GL_ZERO, GL_ONE);
7097 R_SetupGenericShader(false);
7099 GL_BlendFunc(GL_ONE, GL_ZERO);
7101 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7102 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7103 if (skyrendermasked)
7104 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7106 R_Mesh_ResetTextureState();
7107 GL_Color(1, 1, 1, 1);
7110 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7112 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7115 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7116 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7117 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7118 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7119 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7120 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7121 if (rsurface.texture->backgroundcurrentskinframe)
7123 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7124 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7125 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7126 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7128 if(rsurface.texture->colormapping)
7130 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7131 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7133 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7134 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7135 R_Mesh_ColorPointer(NULL, 0, 0);
7137 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7139 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7141 // render background
7142 GL_BlendFunc(GL_ONE, GL_ZERO);
7144 GL_AlphaTest(false);
7146 GL_Color(1, 1, 1, 1);
7147 R_Mesh_ColorPointer(NULL, 0, 0);
7149 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7150 if (r_glsl_permutation)
7152 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7153 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7154 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7155 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7156 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7157 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7158 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);
7160 GL_LockArrays(0, 0);
7162 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7163 GL_DepthMask(false);
7164 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7165 R_Mesh_ColorPointer(NULL, 0, 0);
7167 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7168 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7169 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7172 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7173 if (!r_glsl_permutation)
7176 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7177 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7178 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7179 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7180 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7181 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7183 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7185 GL_BlendFunc(GL_ONE, GL_ZERO);
7187 GL_AlphaTest(false);
7191 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7192 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7193 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7196 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7198 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7199 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);
7201 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7205 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7206 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);
7208 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7210 GL_LockArrays(0, 0);
7213 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7215 // OpenGL 1.3 path - anything not completely ancient
7216 int texturesurfaceindex;
7217 qboolean applycolor;
7221 const texturelayer_t *layer;
7222 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7224 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7227 int layertexrgbscale;
7228 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7230 if (layerindex == 0)
7234 GL_AlphaTest(false);
7235 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7238 GL_DepthMask(layer->depthmask && writedepth);
7239 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7240 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7242 layertexrgbscale = 4;
7243 VectorScale(layer->color, 0.25f, layercolor);
7245 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7247 layertexrgbscale = 2;
7248 VectorScale(layer->color, 0.5f, layercolor);
7252 layertexrgbscale = 1;
7253 VectorScale(layer->color, 1.0f, layercolor);
7255 layercolor[3] = layer->color[3];
7256 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7257 R_Mesh_ColorPointer(NULL, 0, 0);
7258 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7259 switch (layer->type)
7261 case TEXTURELAYERTYPE_LITTEXTURE:
7262 memset(&m, 0, sizeof(m));
7263 m.tex[0] = R_GetTexture(r_texture_white);
7264 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7265 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7266 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7267 m.tex[1] = R_GetTexture(layer->texture);
7268 m.texmatrix[1] = layer->texmatrix;
7269 m.texrgbscale[1] = layertexrgbscale;
7270 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7271 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7272 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7273 R_Mesh_TextureState(&m);
7274 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7275 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7276 else if (rsurface.uselightmaptexture)
7277 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7279 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7281 case TEXTURELAYERTYPE_TEXTURE:
7282 memset(&m, 0, sizeof(m));
7283 m.tex[0] = R_GetTexture(layer->texture);
7284 m.texmatrix[0] = layer->texmatrix;
7285 m.texrgbscale[0] = layertexrgbscale;
7286 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7287 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7288 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7289 R_Mesh_TextureState(&m);
7290 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7292 case TEXTURELAYERTYPE_FOG:
7293 memset(&m, 0, sizeof(m));
7294 m.texrgbscale[0] = layertexrgbscale;
7297 m.tex[0] = R_GetTexture(layer->texture);
7298 m.texmatrix[0] = layer->texmatrix;
7299 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7300 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7301 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7303 R_Mesh_TextureState(&m);
7304 // generate a color array for the fog pass
7305 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7306 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7310 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7311 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)
7313 f = 1 - RSurf_FogVertex(v);
7314 c[0] = layercolor[0];
7315 c[1] = layercolor[1];
7316 c[2] = layercolor[2];
7317 c[3] = f * layercolor[3];
7320 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7323 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7325 GL_LockArrays(0, 0);
7328 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7330 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7331 GL_AlphaTest(false);
7335 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7337 // OpenGL 1.1 - crusty old voodoo path
7338 int texturesurfaceindex;
7342 const texturelayer_t *layer;
7343 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7345 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7347 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7349 if (layerindex == 0)
7353 GL_AlphaTest(false);
7354 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7357 GL_DepthMask(layer->depthmask && writedepth);
7358 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7359 R_Mesh_ColorPointer(NULL, 0, 0);
7360 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7361 switch (layer->type)
7363 case TEXTURELAYERTYPE_LITTEXTURE:
7364 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7366 // two-pass lit texture with 2x rgbscale
7367 // first the lightmap pass
7368 memset(&m, 0, sizeof(m));
7369 m.tex[0] = R_GetTexture(r_texture_white);
7370 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7371 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7372 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7373 R_Mesh_TextureState(&m);
7374 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7375 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7376 else if (rsurface.uselightmaptexture)
7377 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7379 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7380 GL_LockArrays(0, 0);
7381 // then apply the texture to it
7382 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7383 memset(&m, 0, sizeof(m));
7384 m.tex[0] = R_GetTexture(layer->texture);
7385 m.texmatrix[0] = layer->texmatrix;
7386 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7387 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7388 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7389 R_Mesh_TextureState(&m);
7390 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);
7394 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7395 memset(&m, 0, sizeof(m));
7396 m.tex[0] = R_GetTexture(layer->texture);
7397 m.texmatrix[0] = layer->texmatrix;
7398 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7399 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7400 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7401 R_Mesh_TextureState(&m);
7402 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7403 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);
7405 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);
7408 case TEXTURELAYERTYPE_TEXTURE:
7409 // singletexture unlit texture with transparency support
7410 memset(&m, 0, sizeof(m));
7411 m.tex[0] = R_GetTexture(layer->texture);
7412 m.texmatrix[0] = layer->texmatrix;
7413 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7414 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7415 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7416 R_Mesh_TextureState(&m);
7417 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);
7419 case TEXTURELAYERTYPE_FOG:
7420 // singletexture fogging
7421 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7424 memset(&m, 0, sizeof(m));
7425 m.tex[0] = R_GetTexture(layer->texture);
7426 m.texmatrix[0] = layer->texmatrix;
7427 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7428 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7429 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7430 R_Mesh_TextureState(&m);
7433 R_Mesh_ResetTextureState();
7434 // generate a color array for the fog pass
7435 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7439 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7440 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)
7442 f = 1 - RSurf_FogVertex(v);
7443 c[0] = layer->color[0];
7444 c[1] = layer->color[1];
7445 c[2] = layer->color[2];
7446 c[3] = f * layer->color[3];
7449 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7452 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7454 GL_LockArrays(0, 0);
7457 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7459 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7460 GL_AlphaTest(false);
7464 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7468 GL_AlphaTest(false);
7469 R_Mesh_ColorPointer(NULL, 0, 0);
7470 R_Mesh_ResetTextureState();
7471 R_SetupGenericShader(false);
7473 if(rsurface.texture && rsurface.texture->currentskinframe)
7475 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7476 c[3] *= rsurface.texture->currentalpha;
7486 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7488 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7489 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7490 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7493 // brighten it up (as texture value 127 means "unlit")
7494 c[0] *= 2 * r_refdef.view.colorscale;
7495 c[1] *= 2 * r_refdef.view.colorscale;
7496 c[2] *= 2 * r_refdef.view.colorscale;
7498 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7499 c[3] *= r_wateralpha.value;
7501 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7503 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7504 GL_DepthMask(false);
7506 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7508 GL_BlendFunc(GL_ONE, GL_ONE);
7509 GL_DepthMask(false);
7511 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7513 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7514 GL_DepthMask(false);
7516 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7518 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7519 GL_DepthMask(false);
7523 GL_BlendFunc(GL_ONE, GL_ZERO);
7524 GL_DepthMask(writedepth);
7527 rsurface.lightmapcolor4f = NULL;
7529 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7531 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7533 rsurface.lightmapcolor4f = NULL;
7534 rsurface.lightmapcolor4f_bufferobject = 0;
7535 rsurface.lightmapcolor4f_bufferoffset = 0;
7537 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7539 qboolean applycolor = true;
7542 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7544 r_refdef.lightmapintensity = 1;
7545 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7546 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7550 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7552 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7553 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7554 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7557 if(!rsurface.lightmapcolor4f)
7558 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7560 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7561 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7562 if(r_refdef.fogenabled)
7563 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7565 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7566 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7569 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7572 RSurf_SetupDepthAndCulling();
7573 if (r_showsurfaces.integer == 3)
7574 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7575 else if (r_glsl.integer && gl_support_fragment_shader)
7576 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7577 else if (gl_combine.integer && r_textureunits.integer >= 2)
7578 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7580 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7584 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7587 RSurf_SetupDepthAndCulling();
7588 if (r_showsurfaces.integer == 3)
7589 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7590 else if (r_glsl.integer && gl_support_fragment_shader)
7591 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7592 else if (gl_combine.integer && r_textureunits.integer >= 2)
7593 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7595 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7599 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7602 int texturenumsurfaces, endsurface;
7604 msurface_t *surface;
7605 msurface_t *texturesurfacelist[1024];
7607 // if the model is static it doesn't matter what value we give for
7608 // wantnormals and wanttangents, so this logic uses only rules applicable
7609 // to a model, knowing that they are meaningless otherwise
7610 if (ent == r_refdef.scene.worldentity)
7611 RSurf_ActiveWorldEntity();
7612 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7613 RSurf_ActiveModelEntity(ent, false, false);
7615 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7617 for (i = 0;i < numsurfaces;i = j)
7620 surface = rsurface.modelsurfaces + surfacelist[i];
7621 texture = surface->texture;
7622 rsurface.texture = R_GetCurrentTexture(texture);
7623 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7624 // scan ahead until we find a different texture
7625 endsurface = min(i + 1024, numsurfaces);
7626 texturenumsurfaces = 0;
7627 texturesurfacelist[texturenumsurfaces++] = surface;
7628 for (;j < endsurface;j++)
7630 surface = rsurface.modelsurfaces + surfacelist[j];
7631 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7633 texturesurfacelist[texturenumsurfaces++] = surface;
7635 // render the range of surfaces
7636 if (ent == r_refdef.scene.worldentity)
7637 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7639 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7641 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7642 GL_AlphaTest(false);
7645 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7647 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7651 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7653 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7655 RSurf_SetupDepthAndCulling();
7656 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7657 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7659 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7661 RSurf_SetupDepthAndCulling();
7662 GL_AlphaTest(false);
7663 R_Mesh_ColorPointer(NULL, 0, 0);
7664 R_Mesh_ResetTextureState();
7665 R_SetupGenericShader(false);
7666 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7668 GL_BlendFunc(GL_ONE, GL_ZERO);
7669 GL_Color(0, 0, 0, 1);
7670 GL_DepthTest(writedepth);
7671 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7673 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7675 RSurf_SetupDepthAndCulling();
7676 GL_AlphaTest(false);
7677 R_Mesh_ColorPointer(NULL, 0, 0);
7678 R_Mesh_ResetTextureState();
7679 R_SetupGenericShader(false);
7680 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7682 GL_BlendFunc(GL_ONE, GL_ZERO);
7684 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7686 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7687 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7688 else if (!rsurface.texture->currentnumlayers)
7690 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7692 // transparent surfaces get pushed off into the transparent queue
7693 int surfacelistindex;
7694 const msurface_t *surface;
7695 vec3_t tempcenter, center;
7696 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7698 surface = texturesurfacelist[surfacelistindex];
7699 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7700 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7701 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7702 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7703 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7708 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7709 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7714 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7718 // break the surface list down into batches by texture and use of lightmapping
7719 for (i = 0;i < numsurfaces;i = j)
7722 // texture is the base texture pointer, rsurface.texture is the
7723 // current frame/skin the texture is directing us to use (for example
7724 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7725 // use skin 1 instead)
7726 texture = surfacelist[i]->texture;
7727 rsurface.texture = R_GetCurrentTexture(texture);
7728 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7729 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7731 // if this texture is not the kind we want, skip ahead to the next one
7732 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7736 // simply scan ahead until we find a different texture or lightmap state
7737 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7739 // render the range of surfaces
7740 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7744 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7749 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7751 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7753 RSurf_SetupDepthAndCulling();
7754 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7755 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7757 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7759 RSurf_SetupDepthAndCulling();
7760 GL_AlphaTest(false);
7761 R_Mesh_ColorPointer(NULL, 0, 0);
7762 R_Mesh_ResetTextureState();
7763 R_SetupGenericShader(false);
7764 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7766 GL_BlendFunc(GL_ONE, GL_ZERO);
7767 GL_Color(0, 0, 0, 1);
7768 GL_DepthTest(writedepth);
7769 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7771 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7773 RSurf_SetupDepthAndCulling();
7774 GL_AlphaTest(false);
7775 R_Mesh_ColorPointer(NULL, 0, 0);
7776 R_Mesh_ResetTextureState();
7777 R_SetupGenericShader(false);
7778 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7780 GL_BlendFunc(GL_ONE, GL_ZERO);
7782 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7784 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7785 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7786 else if (!rsurface.texture->currentnumlayers)
7788 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7790 // transparent surfaces get pushed off into the transparent queue
7791 int surfacelistindex;
7792 const msurface_t *surface;
7793 vec3_t tempcenter, center;
7794 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7796 surface = texturesurfacelist[surfacelistindex];
7797 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7798 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7799 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7800 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7801 if (queueentity->transparent_offset) // transparent offset
7803 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
7804 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
7805 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
7807 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7812 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7813 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7818 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7822 // break the surface list down into batches by texture and use of lightmapping
7823 for (i = 0;i < numsurfaces;i = j)
7826 // texture is the base texture pointer, rsurface.texture is the
7827 // current frame/skin the texture is directing us to use (for example
7828 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7829 // use skin 1 instead)
7830 texture = surfacelist[i]->texture;
7831 rsurface.texture = R_GetCurrentTexture(texture);
7832 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7833 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7835 // if this texture is not the kind we want, skip ahead to the next one
7836 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7840 // simply scan ahead until we find a different texture or lightmap state
7841 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7843 // render the range of surfaces
7844 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7848 float locboxvertex3f[6*4*3] =
7850 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7851 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7852 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7853 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7854 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7855 1,0,0, 0,0,0, 0,1,0, 1,1,0
7858 unsigned short locboxelements[6*2*3] =
7868 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7871 cl_locnode_t *loc = (cl_locnode_t *)ent;
7873 float vertex3f[6*4*3];
7875 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7876 GL_DepthMask(false);
7877 GL_DepthRange(0, 1);
7878 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7880 GL_CullFace(GL_NONE);
7881 R_Mesh_Matrix(&identitymatrix);
7883 R_Mesh_VertexPointer(vertex3f, 0, 0);
7884 R_Mesh_ColorPointer(NULL, 0, 0);
7885 R_Mesh_ResetTextureState();
7886 R_SetupGenericShader(false);
7889 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7890 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7891 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7892 surfacelist[0] < 0 ? 0.5f : 0.125f);
7894 if (VectorCompare(loc->mins, loc->maxs))
7896 VectorSet(size, 2, 2, 2);
7897 VectorMA(loc->mins, -0.5f, size, mins);
7901 VectorCopy(loc->mins, mins);
7902 VectorSubtract(loc->maxs, loc->mins, size);
7905 for (i = 0;i < 6*4*3;)
7906 for (j = 0;j < 3;j++, i++)
7907 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7909 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7912 void R_DrawLocs(void)
7915 cl_locnode_t *loc, *nearestloc;
7917 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7918 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7920 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7921 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7925 void R_DrawDebugModel(entity_render_t *ent)
7927 int i, j, k, l, flagsmask;
7928 const int *elements;
7930 msurface_t *surface;
7931 dp_model_t *model = ent->model;
7934 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7936 R_Mesh_ColorPointer(NULL, 0, 0);
7937 R_Mesh_ResetTextureState();
7938 R_SetupGenericShader(false);
7939 GL_DepthRange(0, 1);
7940 GL_DepthTest(!r_showdisabledepthtest.integer);
7941 GL_DepthMask(false);
7942 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7944 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7946 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7947 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7949 if (brush->colbrushf && brush->colbrushf->numtriangles)
7951 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7952 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);
7953 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7956 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7958 if (surface->num_collisiontriangles)
7960 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7961 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);
7962 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7967 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7969 if (r_showtris.integer || r_shownormals.integer)
7971 if (r_showdisabledepthtest.integer)
7973 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7974 GL_DepthMask(false);
7978 GL_BlendFunc(GL_ONE, GL_ZERO);
7981 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7983 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7985 rsurface.texture = R_GetCurrentTexture(surface->texture);
7986 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7988 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7989 if (r_showtris.value > 0)
7991 if (!rsurface.texture->currentlayers->depthmask)
7992 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7993 else if (ent == r_refdef.scene.worldentity)
7994 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7996 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7997 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7998 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7999 R_Mesh_ColorPointer(NULL, 0, 0);
8000 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8001 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8002 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
8003 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);
8004 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8007 if (r_shownormals.value < 0)
8010 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8012 VectorCopy(rsurface.vertex3f + l * 3, v);
8013 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8014 qglVertex3f(v[0], v[1], v[2]);
8015 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8016 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8017 qglVertex3f(v[0], v[1], v[2]);
8022 if (r_shownormals.value > 0)
8025 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8027 VectorCopy(rsurface.vertex3f + l * 3, v);
8028 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8029 qglVertex3f(v[0], v[1], v[2]);
8030 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8031 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8032 qglVertex3f(v[0], v[1], v[2]);
8037 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8039 VectorCopy(rsurface.vertex3f + l * 3, v);
8040 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8041 qglVertex3f(v[0], v[1], v[2]);
8042 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8043 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8044 qglVertex3f(v[0], v[1], v[2]);
8049 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8051 VectorCopy(rsurface.vertex3f + l * 3, v);
8052 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8053 qglVertex3f(v[0], v[1], v[2]);
8054 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8055 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8056 qglVertex3f(v[0], v[1], v[2]);
8063 rsurface.texture = NULL;
8067 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8068 int r_maxsurfacelist = 0;
8069 msurface_t **r_surfacelist = NULL;
8070 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8072 int i, j, endj, f, flagsmask;
8074 dp_model_t *model = r_refdef.scene.worldmodel;
8075 msurface_t *surfaces;
8076 unsigned char *update;
8077 int numsurfacelist = 0;
8081 if (r_maxsurfacelist < model->num_surfaces)
8083 r_maxsurfacelist = model->num_surfaces;
8085 Mem_Free(r_surfacelist);
8086 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8089 RSurf_ActiveWorldEntity();
8091 surfaces = model->data_surfaces;
8092 update = model->brushq1.lightmapupdateflags;
8094 // update light styles on this submodel
8095 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8097 model_brush_lightstyleinfo_t *style;
8098 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8100 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8102 int *list = style->surfacelist;
8103 style->value = r_refdef.scene.lightstylevalue[style->style];
8104 for (j = 0;j < style->numsurfaces;j++)
8105 update[list[j]] = true;
8110 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8114 R_DrawDebugModel(r_refdef.scene.worldentity);
8115 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8121 rsurface.uselightmaptexture = false;
8122 rsurface.texture = NULL;
8123 rsurface.rtlight = NULL;
8125 // add visible surfaces to draw list
8126 for (i = 0;i < model->nummodelsurfaces;i++)
8128 j = model->sortedmodelsurfaces[i];
8129 if (r_refdef.viewcache.world_surfacevisible[j])
8130 r_surfacelist[numsurfacelist++] = surfaces + j;
8132 // update lightmaps if needed
8134 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8135 if (r_refdef.viewcache.world_surfacevisible[j])
8137 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8138 // don't do anything if there were no surfaces
8139 if (!numsurfacelist)
8141 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8144 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8145 GL_AlphaTest(false);
8147 // add to stats if desired
8148 if (r_speeds.integer && !skysurfaces && !depthonly)
8150 r_refdef.stats.world_surfaces += numsurfacelist;
8151 for (j = 0;j < numsurfacelist;j++)
8152 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8154 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8157 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8159 int i, j, endj, f, flagsmask;
8161 dp_model_t *model = ent->model;
8162 msurface_t *surfaces;
8163 unsigned char *update;
8164 int numsurfacelist = 0;
8168 if (r_maxsurfacelist < model->num_surfaces)
8170 r_maxsurfacelist = model->num_surfaces;
8172 Mem_Free(r_surfacelist);
8173 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8176 // if the model is static it doesn't matter what value we give for
8177 // wantnormals and wanttangents, so this logic uses only rules applicable
8178 // to a model, knowing that they are meaningless otherwise
8179 if (ent == r_refdef.scene.worldentity)
8180 RSurf_ActiveWorldEntity();
8181 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8182 RSurf_ActiveModelEntity(ent, false, false);
8184 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8186 surfaces = model->data_surfaces;
8187 update = model->brushq1.lightmapupdateflags;
8189 // update light styles
8190 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8192 model_brush_lightstyleinfo_t *style;
8193 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8195 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8197 int *list = style->surfacelist;
8198 style->value = r_refdef.scene.lightstylevalue[style->style];
8199 for (j = 0;j < style->numsurfaces;j++)
8200 update[list[j]] = true;
8205 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8209 R_DrawDebugModel(ent);
8210 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8216 rsurface.uselightmaptexture = false;
8217 rsurface.texture = NULL;
8218 rsurface.rtlight = NULL;
8220 // add visible surfaces to draw list
8221 for (i = 0;i < model->nummodelsurfaces;i++)
8222 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8223 // don't do anything if there were no surfaces
8224 if (!numsurfacelist)
8226 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8229 // update lightmaps if needed
8231 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8233 R_BuildLightMap(ent, surfaces + j);
8234 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8235 GL_AlphaTest(false);
8237 // add to stats if desired
8238 if (r_speeds.integer && !skysurfaces && !depthonly)
8240 r_refdef.stats.entities_surfaces += numsurfacelist;
8241 for (j = 0;j < numsurfacelist;j++)
8242 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8244 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity