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", "0.5", "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", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
89 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
90 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
91 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
92 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
94 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
95 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
96 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
97 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
98 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
99 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
100 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
101 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
103 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)"};
105 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
106 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)"};
107 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
108 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
109 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
110 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
111 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)"};
112 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)"};
113 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)"};
114 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)"};
115 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)"};
117 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)"};
118 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
119 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"};
120 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
121 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
123 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
124 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
125 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
126 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
128 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
129 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
130 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
131 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
132 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
133 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
134 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
136 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
137 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
138 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
139 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)"};
141 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"};
143 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"};
145 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
147 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
148 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
149 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"};
150 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
151 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
152 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
153 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
155 extern cvar_t v_glslgamma;
157 extern qboolean v_flipped_state;
159 static struct r_bloomstate_s
164 int bloomwidth, bloomheight;
166 int screentexturewidth, screentextureheight;
167 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
169 int bloomtexturewidth, bloomtextureheight;
170 rtexture_t *texture_bloom;
172 // arrays for rendering the screen passes
173 float screentexcoord2f[8];
174 float bloomtexcoord2f[8];
175 float offsettexcoord2f[8];
177 r_viewport_t viewport;
181 r_waterstate_t r_waterstate;
183 /// shadow volume bsp struct with automatically growing nodes buffer
186 rtexture_t *r_texture_blanknormalmap;
187 rtexture_t *r_texture_white;
188 rtexture_t *r_texture_grey128;
189 rtexture_t *r_texture_black;
190 rtexture_t *r_texture_notexture;
191 rtexture_t *r_texture_whitecube;
192 rtexture_t *r_texture_normalizationcube;
193 rtexture_t *r_texture_fogattenuation;
194 rtexture_t *r_texture_gammaramps;
195 unsigned int r_texture_gammaramps_serial;
196 //rtexture_t *r_texture_fogintensity;
198 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
199 unsigned int r_numqueries;
200 unsigned int r_maxqueries;
202 typedef struct r_qwskincache_s
204 char name[MAX_QPATH];
205 skinframe_t *skinframe;
209 static r_qwskincache_t *r_qwskincache;
210 static int r_qwskincache_size;
212 /// vertex coordinates for a quad that covers the screen exactly
213 const float r_screenvertex3f[12] =
221 extern void R_DrawModelShadows(void);
223 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
226 for (i = 0;i < verts;i++)
237 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
240 for (i = 0;i < verts;i++)
250 // FIXME: move this to client?
253 if (gamemode == GAME_NEHAHRA)
255 Cvar_Set("gl_fogenable", "0");
256 Cvar_Set("gl_fogdensity", "0.2");
257 Cvar_Set("gl_fogred", "0.3");
258 Cvar_Set("gl_foggreen", "0.3");
259 Cvar_Set("gl_fogblue", "0.3");
261 r_refdef.fog_density = 0;
262 r_refdef.fog_red = 0;
263 r_refdef.fog_green = 0;
264 r_refdef.fog_blue = 0;
265 r_refdef.fog_alpha = 1;
266 r_refdef.fog_start = 0;
267 r_refdef.fog_end = 16384;
268 r_refdef.fog_height = 1<<30;
269 r_refdef.fog_fadedepth = 128;
272 static void R_BuildBlankTextures(void)
274 unsigned char data[4];
275 data[2] = 128; // normal X
276 data[1] = 128; // normal Y
277 data[0] = 255; // normal Z
278 data[3] = 128; // height
279 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
284 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
289 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
294 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
297 static void R_BuildNoTexture(void)
300 unsigned char pix[16][16][4];
301 // this makes a light grey/dark grey checkerboard texture
302 for (y = 0;y < 16;y++)
304 for (x = 0;x < 16;x++)
306 if ((y < 8) ^ (x < 8))
322 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
325 static void R_BuildWhiteCube(void)
327 unsigned char data[6*1*1*4];
328 memset(data, 255, sizeof(data));
329 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
332 static void R_BuildNormalizationCube(void)
336 vec_t s, t, intensity;
338 unsigned char data[6][NORMSIZE][NORMSIZE][4];
339 for (side = 0;side < 6;side++)
341 for (y = 0;y < NORMSIZE;y++)
343 for (x = 0;x < NORMSIZE;x++)
345 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
346 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
381 intensity = 127.0f / sqrt(DotProduct(v, v));
382 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
383 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
384 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
385 data[side][y][x][3] = 255;
389 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
392 static void R_BuildFogTexture(void)
396 unsigned char data1[FOGWIDTH][4];
397 //unsigned char data2[FOGWIDTH][4];
400 r_refdef.fogmasktable_start = r_refdef.fog_start;
401 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
402 r_refdef.fogmasktable_range = r_refdef.fogrange;
403 r_refdef.fogmasktable_density = r_refdef.fog_density;
405 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
406 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
408 d = (x * r - r_refdef.fogmasktable_start);
409 if(developer.integer >= 100)
410 Con_Printf("%f ", d);
412 if (r_fog_exp2.integer)
413 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
415 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
416 if(developer.integer >= 100)
417 Con_Printf(" : %f ", alpha);
418 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
419 if(developer.integer >= 100)
420 Con_Printf(" = %f\n", alpha);
421 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
424 for (x = 0;x < FOGWIDTH;x++)
426 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
431 //data2[x][0] = 255 - b;
432 //data2[x][1] = 255 - b;
433 //data2[x][2] = 255 - b;
436 if (r_texture_fogattenuation)
438 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
439 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
443 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);
444 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
448 static const char *builtinshaderstring =
449 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
450 "// written by Forest 'LordHavoc' Hale\n"
452 "// enable various extensions depending on permutation:\n"
454 "#ifdef USESHADOWMAPRECT\n"
455 "# extension GL_ARB_texture_rectangle : enable\n"
458 "#ifdef USESHADOWMAP2D\n"
459 "# ifdef GL_EXT_gpu_shader4\n"
460 "# extension GL_EXT_gpu_shader4 : enable\n"
462 "# ifdef GL_ARB_texture_gather\n"
463 "# extension GL_ARB_texture_gather : enable\n"
465 "# ifdef GL_AMD_texture_texture4\n"
466 "# extension GL_AMD_texture_texture4 : enable\n"
471 "#ifdef USESHADOWMAPCUBE\n"
472 "# extension GL_EXT_gpu_shader4 : enable\n"
475 "#ifdef USESHADOWSAMPLER\n"
476 "# extension GL_ARB_shadow : enable\n"
479 "// common definitions between vertex shader and fragment shader:\n"
481 "//#ifdef __GLSL_CG_DATA_TYPES\n"
482 "//# define myhalf half\n"
483 "//# define myhalf2 half2\n"
484 "//# define myhalf3half3\n"
485 "//# define myhalf4 half4\n"
487 "# define myhalf float\n"
488 "# define myhalf2 vec2\n"
489 "# define myhalf3 vec3\n"
490 "# define myhalf4 vec4\n"
493 "#ifdef USEFOGINSIDE\n"
496 "# ifdef USEFOGOUTSIDE\n"
501 "#ifdef MODE_DEPTH_OR_SHADOW\n"
503 "# ifdef VERTEX_SHADER\n"
506 " gl_Position = ftransform();\n"
511 "#ifdef MODE_SHOWDEPTH\n"
512 "# ifdef VERTEX_SHADER\n"
515 " gl_Position = ftransform();\n"
516 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
519 "# ifdef FRAGMENT_SHADER\n"
522 " gl_FragColor = gl_Color;\n"
526 "#else // !MODE_SHOWDEPTH\n"
528 "#ifdef MODE_POSTPROCESS\n"
529 "# ifdef VERTEX_SHADER\n"
532 " gl_FrontColor = gl_Color;\n"
533 " gl_Position = ftransform();\n"
534 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
536 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
540 "# ifdef FRAGMENT_SHADER\n"
542 "uniform sampler2D Texture_First;\n"
544 "uniform sampler2D Texture_Second;\n"
546 "#ifdef USEGAMMARAMPS\n"
547 "uniform sampler2D Texture_GammaRamps;\n"
549 "#ifdef USESATURATION\n"
550 "uniform float Saturation;\n"
552 "#ifdef USEVIEWTINT\n"
553 "uniform vec4 TintColor;\n"
555 "//uncomment these if you want to use them:\n"
556 "uniform vec4 UserVec1;\n"
557 "// uniform vec4 UserVec2;\n"
558 "// uniform vec4 UserVec3;\n"
559 "// uniform vec4 UserVec4;\n"
560 "// uniform float ClientTime;\n"
561 "uniform vec2 PixelSize;\n"
564 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
566 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
568 "#ifdef USEVIEWTINT\n"
569 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
572 "#ifdef USEPOSTPROCESSING\n"
573 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
574 "// 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"
575 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
576 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
577 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
578 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
579 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
580 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
583 "#ifdef USESATURATION\n"
584 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
585 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
586 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
587 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
590 "#ifdef USEGAMMARAMPS\n"
591 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
592 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
593 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
600 "#ifdef MODE_GENERIC\n"
601 "# ifdef VERTEX_SHADER\n"
604 " gl_FrontColor = gl_Color;\n"
605 "# ifdef USEDIFFUSE\n"
606 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
608 "# ifdef USESPECULAR\n"
609 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
611 " gl_Position = ftransform();\n"
614 "# ifdef FRAGMENT_SHADER\n"
616 "# ifdef USEDIFFUSE\n"
617 "uniform sampler2D Texture_First;\n"
619 "# ifdef USESPECULAR\n"
620 "uniform sampler2D Texture_Second;\n"
625 " gl_FragColor = gl_Color;\n"
626 "# ifdef USEDIFFUSE\n"
627 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
630 "# ifdef USESPECULAR\n"
631 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
633 "# ifdef USECOLORMAPPING\n"
634 " gl_FragColor *= tex2;\n"
637 " gl_FragColor += tex2;\n"
639 "# ifdef USEVERTEXTEXTUREBLEND\n"
640 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
645 "#else // !MODE_GENERIC\n"
646 "#ifdef MODE_BLOOMBLUR\n"
647 "# ifdef VERTEX_SHADER\n"
650 " gl_FrontColor = gl_Color;\n"
651 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
652 " gl_Position = ftransform();\n"
655 "# ifdef FRAGMENT_SHADER\n"
657 "uniform sampler2D Texture_First;\n"
658 "uniform vec4 BloomBlur_Parameters;\n"
663 " vec2 tc = gl_TexCoord[0].xy;\n"
664 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
665 " tc += BloomBlur_Parameters.xy;\n"
666 " for (i = 1;i < SAMPLES;i++)\n"
668 " color += texture2D(Texture_First, tc).rgb;\n"
669 " tc += BloomBlur_Parameters.xy;\n"
671 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
675 "#else // !MODE_BLOOMBLUR\n"
677 "varying vec2 TexCoord;\n"
678 "#ifdef USEVERTEXTEXTUREBLEND\n"
679 "varying vec2 TexCoord2;\n"
681 "varying vec2 TexCoordLightmap;\n"
683 "#ifdef MODE_LIGHTSOURCE\n"
684 "varying vec3 CubeVector;\n"
687 "#ifdef MODE_LIGHTSOURCE\n"
688 "varying vec3 LightVector;\n"
690 "#ifdef MODE_LIGHTDIRECTION\n"
691 "varying vec3 LightVector;\n"
694 "varying vec3 EyeVector;\n"
696 "varying vec3 EyeVectorModelSpace;\n"
697 "varying float FogPlaneVertexDist;\n"
700 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
701 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
702 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
704 "#ifdef MODE_WATER\n"
705 "varying vec4 ModelViewProjectionPosition;\n"
707 "#ifdef MODE_REFRACTION\n"
708 "varying vec4 ModelViewProjectionPosition;\n"
710 "#ifdef USEREFLECTION\n"
711 "varying vec4 ModelViewProjectionPosition;\n"
718 "// vertex shader specific:\n"
719 "#ifdef VERTEX_SHADER\n"
721 "uniform vec3 LightPosition;\n"
722 "uniform vec3 EyePosition;\n"
723 "uniform vec3 LightDir;\n"
724 "uniform vec4 FogPlane;\n"
726 "// 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"
730 " gl_FrontColor = gl_Color;\n"
731 " // copy the surface texcoord\n"
732 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
733 "#ifdef USEVERTEXTEXTUREBLEND\n"
734 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
736 "#ifndef MODE_LIGHTSOURCE\n"
737 "# ifndef MODE_LIGHTDIRECTION\n"
738 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
742 "#ifdef MODE_LIGHTSOURCE\n"
743 " // transform vertex position into light attenuation/cubemap space\n"
744 " // (-1 to +1 across the light box)\n"
745 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
747 " // transform unnormalized light direction into tangent space\n"
748 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
749 " // normalize it per pixel)\n"
750 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
751 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
752 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
753 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
756 "#ifdef MODE_LIGHTDIRECTION\n"
757 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
758 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
759 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
762 " // transform unnormalized eye direction into tangent space\n"
764 " vec3 EyeVectorModelSpace;\n"
766 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
767 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
768 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
769 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
772 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
775 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
776 " VectorS = gl_MultiTexCoord1.xyz;\n"
777 " VectorT = gl_MultiTexCoord2.xyz;\n"
778 " VectorR = gl_MultiTexCoord3.xyz;\n"
781 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
782 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
783 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
784 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
787 "// transform vertex to camera space, using ftransform to match non-VS\n"
789 " gl_Position = ftransform();\n"
791 "#ifdef MODE_WATER\n"
792 " ModelViewProjectionPosition = gl_Position;\n"
794 "#ifdef MODE_REFRACTION\n"
795 " ModelViewProjectionPosition = gl_Position;\n"
797 "#ifdef USEREFLECTION\n"
798 " ModelViewProjectionPosition = gl_Position;\n"
802 "#endif // VERTEX_SHADER\n"
807 "// fragment shader specific:\n"
808 "#ifdef FRAGMENT_SHADER\n"
810 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
811 "uniform sampler2D Texture_Normal;\n"
812 "uniform sampler2D Texture_Color;\n"
813 "uniform sampler2D Texture_Gloss;\n"
814 "uniform sampler2D Texture_Glow;\n"
815 "uniform sampler2D Texture_SecondaryNormal;\n"
816 "uniform sampler2D Texture_SecondaryColor;\n"
817 "uniform sampler2D Texture_SecondaryGloss;\n"
818 "uniform sampler2D Texture_SecondaryGlow;\n"
819 "uniform sampler2D Texture_Pants;\n"
820 "uniform sampler2D Texture_Shirt;\n"
821 "uniform sampler2D Texture_FogMask;\n"
822 "uniform sampler2D Texture_Lightmap;\n"
823 "uniform sampler2D Texture_Deluxemap;\n"
824 "uniform sampler2D Texture_Refraction;\n"
825 "uniform sampler2D Texture_Reflection;\n"
826 "uniform sampler2D Texture_Attenuation;\n"
827 "uniform samplerCube Texture_Cube;\n"
829 "#define showshadowmap 0\n"
831 "#ifdef USESHADOWMAPRECT\n"
832 "# ifdef USESHADOWSAMPLER\n"
833 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
835 "uniform sampler2DRect Texture_ShadowMapRect;\n"
839 "#ifdef USESHADOWMAP2D\n"
840 "# ifdef USESHADOWSAMPLER\n"
841 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
843 "uniform sampler2D Texture_ShadowMap2D;\n"
847 "#ifdef USESHADOWMAPVSDCT\n"
848 "uniform samplerCube Texture_CubeProjection;\n"
851 "#ifdef USESHADOWMAPCUBE\n"
852 "# ifdef USESHADOWSAMPLER\n"
853 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
855 "uniform samplerCube Texture_ShadowMapCube;\n"
859 "uniform myhalf3 LightColor;\n"
860 "uniform myhalf3 AmbientColor;\n"
861 "uniform myhalf3 DiffuseColor;\n"
862 "uniform myhalf3 SpecularColor;\n"
863 "uniform myhalf3 Color_Pants;\n"
864 "uniform myhalf3 Color_Shirt;\n"
865 "uniform myhalf3 FogColor;\n"
867 "uniform myhalf4 TintColor;\n"
870 "//#ifdef MODE_WATER\n"
871 "uniform vec4 DistortScaleRefractReflect;\n"
872 "uniform vec4 ScreenScaleRefractReflect;\n"
873 "uniform vec4 ScreenCenterRefractReflect;\n"
874 "uniform myhalf4 RefractColor;\n"
875 "uniform myhalf4 ReflectColor;\n"
876 "uniform myhalf ReflectFactor;\n"
877 "uniform myhalf ReflectOffset;\n"
879 "//# ifdef MODE_REFRACTION\n"
880 "//uniform vec4 DistortScaleRefractReflect;\n"
881 "//uniform vec4 ScreenScaleRefractReflect;\n"
882 "//uniform vec4 ScreenCenterRefractReflect;\n"
883 "//uniform myhalf4 RefractColor;\n"
884 "//# ifdef USEREFLECTION\n"
885 "//uniform myhalf4 ReflectColor;\n"
888 "//# ifdef USEREFLECTION\n"
889 "//uniform vec4 DistortScaleRefractReflect;\n"
890 "//uniform vec4 ScreenScaleRefractReflect;\n"
891 "//uniform vec4 ScreenCenterRefractReflect;\n"
892 "//uniform myhalf4 ReflectColor;\n"
897 "uniform myhalf3 GlowColor;\n"
898 "uniform myhalf SceneBrightness;\n"
900 "uniform float OffsetMapping_Scale;\n"
901 "uniform float OffsetMapping_Bias;\n"
902 "uniform float FogRangeRecip;\n"
903 "uniform float FogPlaneViewDist;\n"
904 "uniform float FogHeightFade;\n"
906 "uniform myhalf AmbientScale;\n"
907 "uniform myhalf DiffuseScale;\n"
908 "uniform myhalf SpecularScale;\n"
909 "uniform myhalf SpecularPower;\n"
911 "#ifdef USEOFFSETMAPPING\n"
912 "vec2 OffsetMapping(vec2 TexCoord)\n"
914 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
915 " // 14 sample relief mapping: linear search and then binary search\n"
916 " // this basically steps forward a small amount repeatedly until it finds\n"
917 " // itself inside solid, then jitters forward and back using decreasing\n"
918 " // amounts to find the impact\n"
919 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
920 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
921 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
922 " vec3 RT = vec3(TexCoord, 1);\n"
923 " OffsetVector *= 0.1;\n"
924 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
925 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
926 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
927 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
928 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
929 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
930 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
931 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
932 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
933 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
934 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
935 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
936 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
937 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
940 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
941 " // this basically moves forward the full distance, and then backs up based\n"
942 " // on height of samples\n"
943 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
944 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
945 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
946 " TexCoord += OffsetVector;\n"
947 " OffsetVector *= 0.333;\n"
948 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
949 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
950 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
951 " return TexCoord;\n"
954 "#endif // USEOFFSETMAPPING\n"
956 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
957 "uniform vec2 ShadowMap_TextureScale;\n"
958 "uniform vec4 ShadowMap_Parameters;\n"
961 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
962 "vec3 GetShadowMapTC2D(vec3 dir)\n"
964 " vec3 adir = abs(dir);\n"
965 "# ifndef USESHADOWMAPVSDCT\n"
969 " if (adir.x > adir.y)\n"
971 " if (adir.x > adir.z) // X\n"
975 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
981 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
986 " if (adir.y > adir.z) // Y\n"
990 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
996 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1000 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1001 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1002 " stc.z += ShadowMap_Parameters.z;\n"
1003 "# if showshadowmap\n"
1004 " stc.xy *= ShadowMap_TextureScale;\n"
1008 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1009 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1010 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1011 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1012 " stc.z += ShadowMap_Parameters.z;\n"
1013 "# if showshadowmap\n"
1014 " stc.xy *= ShadowMap_TextureScale;\n"
1019 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1021 "#ifdef USESHADOWMAPCUBE\n"
1022 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1024 " vec3 adir = abs(dir);\n"
1025 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1029 "#if !showshadowmap\n"
1030 "# ifdef USESHADOWMAPRECT\n"
1031 "float ShadowMapCompare(vec3 dir)\n"
1033 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1035 "# ifdef USESHADOWSAMPLER\n"
1037 "# ifdef USESHADOWMAPPCF\n"
1038 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1039 " 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"
1041 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1046 "# ifdef USESHADOWMAPPCF\n"
1047 "# if USESHADOWMAPPCF > 1\n"
1048 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1049 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1050 " 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"
1051 " 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"
1052 " 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"
1053 " 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"
1054 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1055 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1057 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1058 " vec2 offset = fract(shadowmaptc.xy);\n"
1059 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1060 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1061 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1062 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1063 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1066 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1074 "# ifdef USESHADOWMAP2D\n"
1075 "float ShadowMapCompare(vec3 dir)\n"
1077 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1080 "# ifdef USESHADOWSAMPLER\n"
1081 "# ifdef USESHADOWMAPPCF\n"
1082 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1083 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1084 " 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"
1086 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1089 "# ifdef USESHADOWMAPPCF\n"
1090 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1091 "# ifdef GL_ARB_texture_gather\n"
1092 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1094 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1096 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1097 " center *= ShadowMap_TextureScale;\n"
1098 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1099 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1100 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1101 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1102 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1103 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1104 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1106 "# ifdef GL_EXT_gpu_shader4\n"
1107 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1109 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1111 "# if USESHADOWMAPPCF > 1\n"
1112 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1113 " center *= ShadowMap_TextureScale;\n"
1114 " 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"
1115 " 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"
1116 " 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"
1117 " 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"
1118 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1119 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1121 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1122 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1123 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1124 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1125 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1126 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1130 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1137 "# ifdef USESHADOWMAPCUBE\n"
1138 "float ShadowMapCompare(vec3 dir)\n"
1140 " // apply depth texture cubemap as light filter\n"
1141 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1143 "# ifdef USESHADOWSAMPLER\n"
1144 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1146 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1153 "#ifdef MODE_WATER\n"
1158 "#ifdef USEOFFSETMAPPING\n"
1159 " // apply offsetmapping\n"
1160 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1161 "#define TexCoord TexCoordOffset\n"
1164 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1165 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1166 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1167 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1168 " // FIXME temporary hack to detect the case that the reflection\n"
1169 " // gets blackened at edges due to leaving the area that contains actual\n"
1171 " // Remove this 'ack once we have a better way to stop this thing from\n"
1173 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1174 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1175 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1176 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1177 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1178 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1179 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1180 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1181 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1182 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1183 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1184 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1187 "#else // !MODE_WATER\n"
1188 "#ifdef MODE_REFRACTION\n"
1190 "// refraction pass\n"
1193 "#ifdef USEOFFSETMAPPING\n"
1194 " // apply offsetmapping\n"
1195 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1196 "#define TexCoord TexCoordOffset\n"
1199 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1200 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1201 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1202 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1203 " // FIXME temporary hack to detect the case that the reflection\n"
1204 " // gets blackened at edges due to leaving the area that contains actual\n"
1206 " // Remove this 'ack once we have a better way to stop this thing from\n"
1208 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1209 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1210 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1211 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1212 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1213 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1216 "#else // !MODE_REFRACTION\n"
1219 "#ifdef USEOFFSETMAPPING\n"
1220 " // apply offsetmapping\n"
1221 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1222 "#define TexCoord TexCoordOffset\n"
1225 " // combine the diffuse textures (base, pants, shirt)\n"
1226 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1227 "#ifdef USECOLORMAPPING\n"
1228 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1230 "#ifdef USEVERTEXTEXTUREBLEND\n"
1231 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1232 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1233 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1234 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1236 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1239 "#ifdef USEDIFFUSE\n"
1240 " // get the surface normal and the gloss color\n"
1241 "# ifdef USEVERTEXTEXTUREBLEND\n"
1242 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1243 "# ifdef USESPECULAR\n"
1244 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1247 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1248 "# ifdef USESPECULAR\n"
1249 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1256 "#ifdef MODE_LIGHTSOURCE\n"
1257 " // light source\n"
1259 " // calculate surface normal, light normal, and specular normal\n"
1260 " // compute color intensity for the two textures (colormap and glossmap)\n"
1261 " // scale by light color and attenuation as efficiently as possible\n"
1262 " // (do as much scalar math as possible rather than vector math)\n"
1263 "# ifdef USEDIFFUSE\n"
1264 " // get the light normal\n"
1265 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1267 "# ifdef USESPECULAR\n"
1268 "# ifndef USEEXACTSPECULARMATH\n"
1269 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1272 " // calculate directional shading\n"
1273 "# ifdef USEEXACTSPECULARMATH\n"
1274 " 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"
1276 " 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"
1279 "# ifdef USEDIFFUSE\n"
1280 " // calculate directional shading\n"
1281 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1283 " // calculate directionless shading\n"
1284 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1288 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1289 "#if !showshadowmap\n"
1290 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1294 "# ifdef USECUBEFILTER\n"
1295 " // apply light cubemap filter\n"
1296 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1297 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1299 "#endif // MODE_LIGHTSOURCE\n"
1304 "#ifdef MODE_LIGHTDIRECTION\n"
1305 " // directional model lighting\n"
1306 "# ifdef USEDIFFUSE\n"
1307 " // get the light normal\n"
1308 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1310 "# ifdef USESPECULAR\n"
1311 " // calculate directional shading\n"
1312 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1313 "# ifdef USEEXACTSPECULARMATH\n"
1314 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1316 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1317 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1320 "# ifdef USEDIFFUSE\n"
1322 " // calculate directional shading\n"
1323 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1325 " color.rgb *= AmbientColor;\n"
1328 "#endif // MODE_LIGHTDIRECTION\n"
1333 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1334 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1336 " // get the light normal\n"
1337 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1338 " myhalf3 diffusenormal;\n"
1339 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1340 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1341 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1342 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1343 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1344 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1345 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1346 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1347 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1348 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1349 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1350 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1351 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1352 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1353 "# ifdef USESPECULAR\n"
1354 "# ifdef USEEXACTSPECULARMATH\n"
1355 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1357 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1358 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1362 " // apply lightmap color\n"
1363 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1364 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1369 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1370 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1372 " // get the light normal\n"
1373 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1374 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1375 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1376 "# ifdef USESPECULAR\n"
1377 "# ifdef USEEXACTSPECULARMATH\n"
1378 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1380 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1381 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1385 " // apply lightmap color\n"
1386 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1387 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1392 "#ifdef MODE_LIGHTMAP\n"
1393 " // apply lightmap color\n"
1394 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1395 "#endif // MODE_LIGHTMAP\n"
1400 "#ifdef MODE_VERTEXCOLOR\n"
1401 " // apply lightmap color\n"
1402 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1403 "#endif // MODE_VERTEXCOLOR\n"
1408 "#ifdef MODE_FLATCOLOR\n"
1409 "#endif // MODE_FLATCOLOR\n"
1417 " color *= TintColor;\n"
1420 "#ifdef USEVERTEXTEXTUREBLEND\n"
1421 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1423 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1427 " color.rgb *= SceneBrightness;\n"
1429 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1432 "#ifdef USEFOGOUTSIDE\n"
1433 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1435 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1437 "// float FogHeightFade1 = -0.5/1024.0;\n"
1438 "// if (FogPlaneViewDist >= 0.0)\n"
1439 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade1);\n"
1441 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade1);\n"
1442 "//# ifdef USEFOGABOVE\n"
1443 "// if (FogPlaneViewDist >= 0.0)\n"
1444 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist);\n"
1446 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist));\n"
1447 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1448 "// fogfrac *= min(1.0, (max(0.0, fade*FogPlaneVertexDist) + max(0.0, fade*FogPlaneViewDist)));\n"
1449 "// fogfrac *= min(1.0, (max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1450 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1452 " //fogfrac *= min(1.0, max(0.0, (max(-2048, min(0, FogPlaneVertexDist)) + max(-2048, min(0, FogPlaneViewDist)))/-2048.0));\n"
1453 " //float fade = -0.5/128.0;\n"
1454 " //fogfrac *= max(0.0, min(1.0, fade*FogPlaneVertexDist)) + max(0.0, min(1.0, fade*FogPlaneViewDist));\n"
1455 " //fogfrac *= max(0.0, min(1.0, FogHeightFade1*FogPlaneVertexDist)) + max(0.0, min(1.0, FogHeightFade1*FogPlaneViewDist));\n"
1456 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1457 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1458 " //fogfrac *= min(1.0, min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1459 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1460 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1461 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1463 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0))));\n"
1466 " // 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"
1467 "#ifdef USEREFLECTION\n"
1468 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1469 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1470 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1471 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1472 " // FIXME temporary hack to detect the case that the reflection\n"
1473 " // gets blackened at edges due to leaving the area that contains actual\n"
1475 " // Remove this 'ack once we have a better way to stop this thing from\n"
1477 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1478 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1479 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1480 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1481 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1482 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1485 " gl_FragColor = vec4(color);\n"
1487 "#if showshadowmap\n"
1488 "# ifdef USESHADOWMAPRECT\n"
1489 "# ifdef USESHADOWSAMPLER\n"
1490 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1492 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1495 "# ifdef USESHADOWMAP2D\n"
1496 "# ifdef USESHADOWSAMPLER\n"
1497 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1499 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1503 "# ifdef USESHADOWMAPCUBE\n"
1504 "# ifdef USESHADOWSAMPLER\n"
1505 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1507 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1512 "#endif // !MODE_REFRACTION\n"
1513 "#endif // !MODE_WATER\n"
1515 "#endif // FRAGMENT_SHADER\n"
1517 "#endif // !MODE_BLOOMBLUR\n"
1518 "#endif // !MODE_GENERIC\n"
1519 "#endif // !MODE_POSTPROCESS\n"
1520 "#endif // !MODE_SHOWDEPTH\n"
1521 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1524 typedef struct shaderpermutationinfo_s
1526 const char *pretext;
1529 shaderpermutationinfo_t;
1531 typedef struct shadermodeinfo_s
1533 const char *vertexfilename;
1534 const char *geometryfilename;
1535 const char *fragmentfilename;
1536 const char *pretext;
1541 typedef enum shaderpermutation_e
1543 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1544 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1545 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1546 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1547 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1548 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1549 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1550 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1551 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1552 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1553 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1554 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1555 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1556 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1557 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1558 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1559 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1560 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1561 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1562 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1563 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1564 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1565 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1566 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1567 SHADERPERMUTATION_LIMIT = 1<<24, ///< size of permutations array
1568 SHADERPERMUTATION_COUNT = 24 ///< size of shaderpermutationinfo array
1570 shaderpermutation_t;
1572 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1573 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1575 {"#define USEDIFFUSE\n", " diffuse"},
1576 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1577 {"#define USEVIEWTINT\n", " viewtint"},
1578 {"#define USECOLORMAPPING\n", " colormapping"},
1579 {"#define USESATURATION\n", " saturation"},
1580 {"#define USEFOGINSIDE\n", " foginside"},
1581 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1582 {"#define USEGAMMARAMPS\n", " gammaramps"},
1583 {"#define USECUBEFILTER\n", " cubefilter"},
1584 {"#define USEGLOW\n", " glow"},
1585 {"#define USEBLOOM\n", " bloom"},
1586 {"#define USESPECULAR\n", " specular"},
1587 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1588 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1589 {"#define USEREFLECTION\n", " reflection"},
1590 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1591 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1592 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1593 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1594 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1595 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1596 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1597 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1598 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1601 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1602 typedef enum shadermode_e
1604 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1605 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1606 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1607 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1608 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1609 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1610 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1611 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1612 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1613 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1614 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1615 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1616 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1621 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1622 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1624 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1625 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1626 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1627 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1628 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1629 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1630 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1631 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1632 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1633 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1634 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1635 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1636 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1639 struct r_glsl_permutation_s;
1640 typedef struct r_glsl_permutation_s
1642 /// hash lookup data
1643 struct r_glsl_permutation_s *hashnext;
1645 unsigned int permutation;
1647 /// indicates if we have tried compiling this permutation already
1649 /// 0 if compilation failed
1651 /// locations of detected uniforms in program object, or -1 if not found
1652 int loc_Texture_First;
1653 int loc_Texture_Second;
1654 int loc_Texture_GammaRamps;
1655 int loc_Texture_Normal;
1656 int loc_Texture_Color;
1657 int loc_Texture_Gloss;
1658 int loc_Texture_Glow;
1659 int loc_Texture_SecondaryNormal;
1660 int loc_Texture_SecondaryColor;
1661 int loc_Texture_SecondaryGloss;
1662 int loc_Texture_SecondaryGlow;
1663 int loc_Texture_Pants;
1664 int loc_Texture_Shirt;
1665 int loc_Texture_FogMask;
1666 int loc_Texture_Lightmap;
1667 int loc_Texture_Deluxemap;
1668 int loc_Texture_Attenuation;
1669 int loc_Texture_Cube;
1670 int loc_Texture_Refraction;
1671 int loc_Texture_Reflection;
1672 int loc_Texture_ShadowMapRect;
1673 int loc_Texture_ShadowMapCube;
1674 int loc_Texture_ShadowMap2D;
1675 int loc_Texture_CubeProjection;
1677 int loc_LightPosition;
1678 int loc_EyePosition;
1679 int loc_Color_Pants;
1680 int loc_Color_Shirt;
1682 int loc_FogPlaneViewDist;
1683 int loc_FogRangeRecip;
1684 int loc_FogHeightFade;
1685 int loc_AmbientScale;
1686 int loc_DiffuseScale;
1687 int loc_SpecularScale;
1688 int loc_SpecularPower;
1690 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1691 int loc_OffsetMapping_Scale;
1693 int loc_AmbientColor;
1694 int loc_DiffuseColor;
1695 int loc_SpecularColor;
1697 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1698 int loc_GammaCoeff; ///< 1 / gamma
1699 int loc_DistortScaleRefractReflect;
1700 int loc_ScreenScaleRefractReflect;
1701 int loc_ScreenCenterRefractReflect;
1702 int loc_RefractColor;
1703 int loc_ReflectColor;
1704 int loc_ReflectFactor;
1705 int loc_ReflectOffset;
1713 int loc_ShadowMap_TextureScale;
1714 int loc_ShadowMap_Parameters;
1716 r_glsl_permutation_t;
1718 #define SHADERPERMUTATION_HASHSIZE 4096
1720 /// information about each possible shader permutation
1721 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1722 /// currently selected permutation
1723 r_glsl_permutation_t *r_glsl_permutation;
1724 /// storage for permutations linked in the hash table
1725 memexpandablearray_t r_glsl_permutationarray;
1727 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1729 //unsigned int hashdepth = 0;
1730 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1731 r_glsl_permutation_t *p;
1732 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1734 if (p->mode == mode && p->permutation == permutation)
1736 //if (hashdepth > 10)
1737 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1742 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1744 p->permutation = permutation;
1745 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1746 r_glsl_permutationhash[mode][hashindex] = p;
1747 //if (hashdepth > 10)
1748 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1752 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1755 if (!filename || !filename[0])
1757 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1760 if (printfromdisknotice)
1761 Con_DPrint("from disk... ");
1762 return shaderstring;
1764 else if (!strcmp(filename, "glsl/default.glsl"))
1766 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1767 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1769 return shaderstring;
1772 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1775 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1776 int vertstrings_count = 0;
1777 int geomstrings_count = 0;
1778 int fragstrings_count = 0;
1779 char *vertexstring, *geometrystring, *fragmentstring;
1780 const char *vertstrings_list[32+3];
1781 const char *geomstrings_list[32+3];
1782 const char *fragstrings_list[32+3];
1783 char permutationname[256];
1790 permutationname[0] = 0;
1791 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1792 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1793 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1795 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1797 // the first pretext is which type of shader to compile as
1798 // (later these will all be bound together as a program object)
1799 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1800 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1801 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1803 // the second pretext is the mode (for example a light source)
1804 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1805 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1806 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1807 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1809 // now add all the permutation pretexts
1810 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1812 if (permutation & (1<<i))
1814 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1815 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1816 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1817 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1821 // keep line numbers correct
1822 vertstrings_list[vertstrings_count++] = "\n";
1823 geomstrings_list[geomstrings_count++] = "\n";
1824 fragstrings_list[fragstrings_count++] = "\n";
1828 // now append the shader text itself
1829 vertstrings_list[vertstrings_count++] = vertexstring;
1830 geomstrings_list[geomstrings_count++] = geometrystring;
1831 fragstrings_list[fragstrings_count++] = fragmentstring;
1833 // if any sources were NULL, clear the respective list
1835 vertstrings_count = 0;
1836 if (!geometrystring)
1837 geomstrings_count = 0;
1838 if (!fragmentstring)
1839 fragstrings_count = 0;
1841 // compile the shader program
1842 if (vertstrings_count + geomstrings_count + fragstrings_count)
1843 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1847 qglUseProgramObjectARB(p->program);CHECKGLERROR
1848 // look up all the uniform variable names we care about, so we don't
1849 // have to look them up every time we set them
1850 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1851 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1852 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1853 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1854 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1855 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1856 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1857 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1858 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1859 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1860 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1861 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1862 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1863 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1864 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1865 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1866 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1867 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1868 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1869 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1870 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1871 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1872 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1873 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1874 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1875 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1876 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1877 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1878 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1879 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
1880 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
1881 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1882 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
1883 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1884 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1885 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1886 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1887 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1888 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1889 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1890 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1891 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1892 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1893 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1894 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1895 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1896 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1897 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1898 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1899 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1900 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1901 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1902 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1903 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1904 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1905 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1906 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1907 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1908 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1909 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1910 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1911 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1912 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1913 // initialize the samplers to refer to the texture units we use
1914 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1915 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1916 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1917 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1918 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1919 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1920 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1921 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1922 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1923 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1924 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1925 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1926 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1927 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1928 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1929 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1930 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1931 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1932 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1933 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1934 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1935 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1936 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1937 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1939 if (developer.integer)
1940 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1943 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1947 Mem_Free(vertexstring);
1949 Mem_Free(geometrystring);
1951 Mem_Free(fragmentstring);
1954 void R_GLSL_Restart_f(void)
1956 unsigned int i, limit;
1957 r_glsl_permutation_t *p;
1958 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1959 for (i = 0;i < limit;i++)
1961 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1963 GL_Backend_FreeProgram(p->program);
1964 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1967 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1970 void R_GLSL_DumpShader_f(void)
1974 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1977 Con_Printf("failed to write to glsl/default.glsl\n");
1981 FS_Print(file, "/* The engine may define the following macros:\n");
1982 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1983 for (i = 0;i < SHADERMODE_COUNT;i++)
1984 FS_Print(file, shadermodeinfo[i].pretext);
1985 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1986 FS_Print(file, shaderpermutationinfo[i].pretext);
1987 FS_Print(file, "*/\n");
1988 FS_Print(file, builtinshaderstring);
1991 Con_Printf("glsl/default.glsl written\n");
1994 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1996 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1997 if (r_glsl_permutation != perm)
1999 r_glsl_permutation = perm;
2000 if (!r_glsl_permutation->program)
2002 if (!r_glsl_permutation->compiled)
2003 R_GLSL_CompilePermutation(perm, mode, permutation);
2004 if (!r_glsl_permutation->program)
2006 // remove features until we find a valid permutation
2008 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2010 // reduce i more quickly whenever it would not remove any bits
2011 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2012 if (!(permutation & j))
2015 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2016 if (!r_glsl_permutation->compiled)
2017 R_GLSL_CompilePermutation(perm, mode, permutation);
2018 if (r_glsl_permutation->program)
2021 if (i >= SHADERPERMUTATION_COUNT)
2023 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");
2024 Cvar_SetValueQuick(&r_glsl, 0);
2025 R_GLSL_Restart_f(); // unload shaders
2026 return; // no bit left to clear
2031 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2035 void R_SetupGenericShader(qboolean usetexture)
2037 if (gl_support_fragment_shader)
2039 if (r_glsl.integer && r_glsl_usegeneric.integer)
2040 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2041 else if (r_glsl_permutation)
2043 r_glsl_permutation = NULL;
2044 qglUseProgramObjectARB(0);CHECKGLERROR
2049 void R_SetupGenericTwoTextureShader(int texturemode)
2051 if (gl_support_fragment_shader)
2053 if (r_glsl.integer && r_glsl_usegeneric.integer)
2054 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))));
2055 else if (r_glsl_permutation)
2057 r_glsl_permutation = NULL;
2058 qglUseProgramObjectARB(0);CHECKGLERROR
2061 if (!r_glsl_permutation)
2063 if (texturemode == GL_DECAL && gl_combine.integer)
2064 texturemode = GL_INTERPOLATE_ARB;
2065 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
2069 void R_SetupDepthOrShadowShader(void)
2071 if (gl_support_fragment_shader)
2073 if (r_glsl.integer && r_glsl_usegeneric.integer)
2074 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2075 else if (r_glsl_permutation)
2077 r_glsl_permutation = NULL;
2078 qglUseProgramObjectARB(0);CHECKGLERROR
2083 void R_SetupShowDepthShader(void)
2085 if (gl_support_fragment_shader)
2087 if (r_glsl.integer && r_glsl_usegeneric.integer)
2088 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2089 else if (r_glsl_permutation)
2091 r_glsl_permutation = NULL;
2092 qglUseProgramObjectARB(0);CHECKGLERROR
2097 extern rtexture_t *r_shadow_attenuationgradienttexture;
2098 extern rtexture_t *r_shadow_attenuation2dtexture;
2099 extern rtexture_t *r_shadow_attenuation3dtexture;
2100 extern qboolean r_shadow_usingshadowmaprect;
2101 extern qboolean r_shadow_usingshadowmapcube;
2102 extern qboolean r_shadow_usingshadowmap2d;
2103 extern float r_shadow_shadowmap_texturescale[2];
2104 extern float r_shadow_shadowmap_parameters[4];
2105 extern qboolean r_shadow_shadowmapvsdct;
2106 extern qboolean r_shadow_shadowmapsampler;
2107 extern int r_shadow_shadowmappcf;
2108 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2110 // select a permutation of the lighting shader appropriate to this
2111 // combination of texture, entity, light source, and fogging, only use the
2112 // minimum features necessary to avoid wasting rendering time in the
2113 // fragment shader on features that are not being used
2114 unsigned int permutation = 0;
2115 unsigned int mode = 0;
2116 // TODO: implement geometry-shader based shadow volumes someday
2117 if (r_glsl_offsetmapping.integer)
2119 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2120 if (r_glsl_offsetmapping_reliefmapping.integer)
2121 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2123 if (rsurfacepass == RSURFPASS_BACKGROUND)
2125 // distorted background
2126 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2127 mode = SHADERMODE_WATER;
2129 mode = SHADERMODE_REFRACTION;
2131 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2134 mode = SHADERMODE_LIGHTSOURCE;
2135 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2136 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2137 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2138 permutation |= SHADERPERMUTATION_CUBEFILTER;
2139 if (diffusescale > 0)
2140 permutation |= SHADERPERMUTATION_DIFFUSE;
2141 if (specularscale > 0)
2142 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2143 if (r_refdef.fogenabled)
2144 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2145 if (rsurface.texture->colormapping)
2146 permutation |= SHADERPERMUTATION_COLORMAPPING;
2147 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2149 if (r_shadow_usingshadowmaprect)
2150 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2151 if (r_shadow_usingshadowmap2d)
2152 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2153 if (r_shadow_usingshadowmapcube)
2154 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2155 else if(r_shadow_shadowmapvsdct)
2156 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2158 if (r_shadow_shadowmapsampler)
2159 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2160 if (r_shadow_shadowmappcf > 1)
2161 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2162 else if (r_shadow_shadowmappcf)
2163 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2166 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2168 // unshaded geometry (fullbright or ambient model lighting)
2169 mode = SHADERMODE_FLATCOLOR;
2170 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2171 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2172 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2173 permutation |= SHADERPERMUTATION_GLOW;
2174 if (r_refdef.fogenabled)
2175 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2176 if (rsurface.texture->colormapping)
2177 permutation |= SHADERPERMUTATION_COLORMAPPING;
2178 if (r_glsl_offsetmapping.integer)
2180 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2181 if (r_glsl_offsetmapping_reliefmapping.integer)
2182 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2184 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2185 permutation |= SHADERPERMUTATION_REFLECTION;
2187 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2189 // directional model lighting
2190 mode = SHADERMODE_LIGHTDIRECTION;
2191 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2192 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2193 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2194 permutation |= SHADERPERMUTATION_GLOW;
2195 permutation |= SHADERPERMUTATION_DIFFUSE;
2196 if (specularscale > 0)
2197 permutation |= SHADERPERMUTATION_SPECULAR;
2198 if (r_refdef.fogenabled)
2199 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2200 if (rsurface.texture->colormapping)
2201 permutation |= SHADERPERMUTATION_COLORMAPPING;
2202 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2203 permutation |= SHADERPERMUTATION_REFLECTION;
2205 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2207 // ambient model lighting
2208 mode = SHADERMODE_LIGHTDIRECTION;
2209 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2210 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2211 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2212 permutation |= SHADERPERMUTATION_GLOW;
2213 if (r_refdef.fogenabled)
2214 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2215 if (rsurface.texture->colormapping)
2216 permutation |= SHADERPERMUTATION_COLORMAPPING;
2217 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2218 permutation |= SHADERPERMUTATION_REFLECTION;
2223 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2225 // deluxemapping (light direction texture)
2226 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2227 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2229 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2230 permutation |= SHADERPERMUTATION_DIFFUSE;
2231 if (specularscale > 0)
2232 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2234 else if (r_glsl_deluxemapping.integer >= 2)
2236 // fake deluxemapping (uniform light direction in tangentspace)
2237 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2238 permutation |= SHADERPERMUTATION_DIFFUSE;
2239 if (specularscale > 0)
2240 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2242 else if (rsurface.uselightmaptexture)
2244 // ordinary lightmapping (q1bsp, q3bsp)
2245 mode = SHADERMODE_LIGHTMAP;
2249 // ordinary vertex coloring (q3bsp)
2250 mode = SHADERMODE_VERTEXCOLOR;
2252 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2253 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2254 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2255 permutation |= SHADERPERMUTATION_GLOW;
2256 if (r_refdef.fogenabled)
2257 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2258 if (rsurface.texture->colormapping)
2259 permutation |= SHADERPERMUTATION_COLORMAPPING;
2260 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2261 permutation |= SHADERPERMUTATION_REFLECTION;
2263 if(permutation & SHADERPERMUTATION_SPECULAR)
2264 if(r_shadow_glossexact.integer)
2265 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2266 R_SetupShader_SetPermutation(mode, permutation);
2267 if (mode == SHADERMODE_LIGHTSOURCE)
2269 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2270 if (permutation & SHADERPERMUTATION_DIFFUSE)
2272 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2273 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2274 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2275 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2279 // ambient only is simpler
2280 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]);
2281 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2282 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2283 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2285 // additive passes are only darkened by fog, not tinted
2286 if (r_glsl_permutation->loc_FogColor >= 0)
2287 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2288 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]);
2289 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]);
2293 if (mode == SHADERMODE_LIGHTDIRECTION)
2295 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);
2296 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);
2297 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);
2298 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]);
2302 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2303 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2304 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2306 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]);
2307 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);
2308 // additive passes are only darkened by fog, not tinted
2309 if (r_glsl_permutation->loc_FogColor >= 0)
2311 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2312 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2314 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2316 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);
2317 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]);
2318 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]);
2319 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2320 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2321 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2322 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2324 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2325 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2326 if (r_glsl_permutation->loc_Color_Pants >= 0)
2328 if (rsurface.texture->currentskinframe->pants)
2329 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2331 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2333 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2335 if (rsurface.texture->currentskinframe->shirt)
2336 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2338 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2340 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2341 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2342 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2343 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2344 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2346 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2350 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2352 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2356 #define SKINFRAME_HASH 1024
2360 int loadsequence; // incremented each level change
2361 memexpandablearray_t array;
2362 skinframe_t *hash[SKINFRAME_HASH];
2365 r_skinframe_t r_skinframe;
2367 void R_SkinFrame_PrepareForPurge(void)
2369 r_skinframe.loadsequence++;
2370 // wrap it without hitting zero
2371 if (r_skinframe.loadsequence >= 200)
2372 r_skinframe.loadsequence = 1;
2375 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2379 // mark the skinframe as used for the purging code
2380 skinframe->loadsequence = r_skinframe.loadsequence;
2383 void R_SkinFrame_Purge(void)
2387 for (i = 0;i < SKINFRAME_HASH;i++)
2389 for (s = r_skinframe.hash[i];s;s = s->next)
2391 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2393 if (s->merged == s->base)
2395 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2396 R_PurgeTexture(s->stain );s->stain = NULL;
2397 R_PurgeTexture(s->merged);s->merged = NULL;
2398 R_PurgeTexture(s->base );s->base = NULL;
2399 R_PurgeTexture(s->pants );s->pants = NULL;
2400 R_PurgeTexture(s->shirt );s->shirt = NULL;
2401 R_PurgeTexture(s->nmap );s->nmap = NULL;
2402 R_PurgeTexture(s->gloss );s->gloss = NULL;
2403 R_PurgeTexture(s->glow );s->glow = NULL;
2404 R_PurgeTexture(s->fog );s->fog = NULL;
2405 s->loadsequence = 0;
2411 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2413 char basename[MAX_QPATH];
2415 Image_StripImageExtension(name, basename, sizeof(basename));
2417 if( last == NULL ) {
2419 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2420 item = r_skinframe.hash[hashindex];
2425 // linearly search through the hash bucket
2426 for( ; item ; item = item->next ) {
2427 if( !strcmp( item->basename, basename ) ) {
2434 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2438 char basename[MAX_QPATH];
2440 Image_StripImageExtension(name, basename, sizeof(basename));
2442 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2443 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2444 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2448 rtexture_t *dyntexture;
2449 // check whether its a dynamic texture
2450 dyntexture = CL_GetDynTexture( basename );
2451 if (!add && !dyntexture)
2453 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2454 memset(item, 0, sizeof(*item));
2455 strlcpy(item->basename, basename, sizeof(item->basename));
2456 item->base = dyntexture; // either NULL or dyntexture handle
2457 item->textureflags = textureflags;
2458 item->comparewidth = comparewidth;
2459 item->compareheight = compareheight;
2460 item->comparecrc = comparecrc;
2461 item->next = r_skinframe.hash[hashindex];
2462 r_skinframe.hash[hashindex] = item;
2464 else if( item->base == NULL )
2466 rtexture_t *dyntexture;
2467 // check whether its a dynamic texture
2468 // 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]
2469 dyntexture = CL_GetDynTexture( basename );
2470 item->base = dyntexture; // either NULL or dyntexture handle
2473 R_SkinFrame_MarkUsed(item);
2477 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2479 unsigned long long avgcolor[5], wsum; \
2487 for(pix = 0; pix < cnt; ++pix) \
2490 for(comp = 0; comp < 3; ++comp) \
2492 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2495 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2497 for(comp = 0; comp < 3; ++comp) \
2498 avgcolor[comp] += getpixel * w; \
2501 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2502 avgcolor[4] += getpixel; \
2504 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2506 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2507 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2508 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2509 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2512 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2514 // FIXME: it should be possible to disable loading various layers using
2515 // cvars, to prevent wasted loading time and memory usage if the user does
2517 qboolean loadnormalmap = true;
2518 qboolean loadgloss = true;
2519 qboolean loadpantsandshirt = true;
2520 qboolean loadglow = true;
2522 unsigned char *pixels;
2523 unsigned char *bumppixels;
2524 unsigned char *basepixels = NULL;
2525 int basepixels_width;
2526 int basepixels_height;
2527 skinframe_t *skinframe;
2532 if (cls.state == ca_dedicated)
2535 // return an existing skinframe if already loaded
2536 // if loading of the first image fails, don't make a new skinframe as it
2537 // would cause all future lookups of this to be missing
2538 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2539 if (skinframe && skinframe->base)
2542 basepixels = loadimagepixelsbgra(name, complain, true);
2543 if (basepixels == NULL)
2546 if (developer_loading.integer)
2547 Con_Printf("loading skin \"%s\"\n", name);
2549 // we've got some pixels to store, so really allocate this new texture now
2551 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2552 skinframe->stain = NULL;
2553 skinframe->merged = NULL;
2554 skinframe->base = r_texture_notexture;
2555 skinframe->pants = NULL;
2556 skinframe->shirt = NULL;
2557 skinframe->nmap = r_texture_blanknormalmap;
2558 skinframe->gloss = NULL;
2559 skinframe->glow = NULL;
2560 skinframe->fog = NULL;
2562 basepixels_width = image_width;
2563 basepixels_height = image_height;
2564 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);
2566 if (textureflags & TEXF_ALPHA)
2568 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2569 if (basepixels[j] < 255)
2571 if (j < basepixels_width * basepixels_height * 4)
2573 // has transparent pixels
2576 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2577 for (j = 0;j < image_width * image_height * 4;j += 4)
2582 pixels[j+3] = basepixels[j+3];
2584 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);
2589 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2590 //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]);
2592 // _norm is the name used by tenebrae and has been adopted as standard
2595 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2597 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);
2601 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2603 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2604 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2605 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);
2607 Mem_Free(bumppixels);
2609 else if (r_shadow_bumpscale_basetexture.value > 0)
2611 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2612 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2613 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);
2617 // _luma is supported for tenebrae compatibility
2618 // (I think it's a very stupid name, but oh well)
2619 // _glow is the preferred name
2620 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;}
2621 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;}
2622 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;}
2623 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;}
2626 Mem_Free(basepixels);
2631 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2633 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL);
2636 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)
2641 for (i = 0;i < width*height;i++)
2642 if (((unsigned char *)&palette[in[i]])[3] > 0)
2644 if (i == width*height)
2647 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2650 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2651 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2654 unsigned char *temp1, *temp2;
2655 skinframe_t *skinframe;
2657 if (cls.state == ca_dedicated)
2660 // if already loaded just return it, otherwise make a new skinframe
2661 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2662 if (skinframe && skinframe->base)
2665 skinframe->stain = NULL;
2666 skinframe->merged = NULL;
2667 skinframe->base = r_texture_notexture;
2668 skinframe->pants = NULL;
2669 skinframe->shirt = NULL;
2670 skinframe->nmap = r_texture_blanknormalmap;
2671 skinframe->gloss = NULL;
2672 skinframe->glow = NULL;
2673 skinframe->fog = NULL;
2675 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2679 if (developer_loading.integer)
2680 Con_Printf("loading 32bit skin \"%s\"\n", name);
2682 if (r_shadow_bumpscale_basetexture.value > 0)
2684 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2685 temp2 = temp1 + width * height * 4;
2686 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2687 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2690 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2691 if (textureflags & TEXF_ALPHA)
2693 for (i = 3;i < width * height * 4;i += 4)
2694 if (skindata[i] < 255)
2696 if (i < width * height * 4)
2698 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2699 memcpy(fogpixels, skindata, width * height * 4);
2700 for (i = 0;i < width * height * 4;i += 4)
2701 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2702 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2703 Mem_Free(fogpixels);
2707 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2708 //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]);
2713 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2716 unsigned char *temp1, *temp2;
2717 unsigned int *palette;
2718 skinframe_t *skinframe;
2720 if (cls.state == ca_dedicated)
2723 // if already loaded just return it, otherwise make a new skinframe
2724 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2725 if (skinframe && skinframe->base)
2728 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2730 skinframe->stain = NULL;
2731 skinframe->merged = NULL;
2732 skinframe->base = r_texture_notexture;
2733 skinframe->pants = NULL;
2734 skinframe->shirt = NULL;
2735 skinframe->nmap = r_texture_blanknormalmap;
2736 skinframe->gloss = NULL;
2737 skinframe->glow = NULL;
2738 skinframe->fog = NULL;
2740 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2744 if (developer_loading.integer)
2745 Con_Printf("loading quake skin \"%s\"\n", name);
2747 if (r_shadow_bumpscale_basetexture.value > 0)
2749 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2750 temp2 = temp1 + width * height * 4;
2751 // use either a custom palette or the quake palette
2752 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2753 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2754 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2757 // use either a custom palette, or the quake palette
2758 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2759 if (loadglowtexture)
2760 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2761 if (loadpantsandshirt)
2763 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2764 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2766 if (skinframe->pants || skinframe->shirt)
2767 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
2768 if (textureflags & TEXF_ALPHA)
2770 for (i = 0;i < width * height;i++)
2771 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2773 if (i < width * height)
2774 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2777 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2778 //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]);
2783 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)
2786 skinframe_t *skinframe;
2788 if (cls.state == ca_dedicated)
2791 // if already loaded just return it, otherwise make a new skinframe
2792 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2793 if (skinframe && skinframe->base)
2796 skinframe->stain = NULL;
2797 skinframe->merged = NULL;
2798 skinframe->base = r_texture_notexture;
2799 skinframe->pants = NULL;
2800 skinframe->shirt = NULL;
2801 skinframe->nmap = r_texture_blanknormalmap;
2802 skinframe->gloss = NULL;
2803 skinframe->glow = NULL;
2804 skinframe->fog = NULL;
2806 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2810 if (developer_loading.integer)
2811 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2813 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, skinframe->basename, palette, skinframe->textureflags, true);
2814 if (textureflags & TEXF_ALPHA)
2816 for (i = 0;i < width * height;i++)
2817 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
2819 if (i < width * height)
2820 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
2823 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2824 //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]);
2829 skinframe_t *R_SkinFrame_LoadMissing(void)
2831 skinframe_t *skinframe;
2833 if (cls.state == ca_dedicated)
2836 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2837 skinframe->stain = NULL;
2838 skinframe->merged = NULL;
2839 skinframe->base = r_texture_notexture;
2840 skinframe->pants = NULL;
2841 skinframe->shirt = NULL;
2842 skinframe->nmap = r_texture_blanknormalmap;
2843 skinframe->gloss = NULL;
2844 skinframe->glow = NULL;
2845 skinframe->fog = NULL;
2847 skinframe->avgcolor[0] = rand() / RAND_MAX;
2848 skinframe->avgcolor[1] = rand() / RAND_MAX;
2849 skinframe->avgcolor[2] = rand() / RAND_MAX;
2850 skinframe->avgcolor[3] = 1;
2855 void gl_main_start(void)
2859 memset(r_queries, 0, sizeof(r_queries));
2861 r_qwskincache = NULL;
2862 r_qwskincache_size = 0;
2864 // set up r_skinframe loading system for textures
2865 memset(&r_skinframe, 0, sizeof(r_skinframe));
2866 r_skinframe.loadsequence = 1;
2867 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2869 r_main_texturepool = R_AllocTexturePool();
2870 R_BuildBlankTextures();
2872 if (gl_texturecubemap)
2875 R_BuildNormalizationCube();
2877 r_texture_fogattenuation = NULL;
2878 r_texture_gammaramps = NULL;
2879 //r_texture_fogintensity = NULL;
2880 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2881 memset(&r_waterstate, 0, sizeof(r_waterstate));
2882 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2883 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2884 memset(&r_svbsp, 0, sizeof (r_svbsp));
2886 r_refdef.fogmasktable_density = 0;
2889 extern rtexture_t *loadingscreentexture;
2890 void gl_main_shutdown(void)
2893 qglDeleteQueriesARB(r_maxqueries, r_queries);
2897 memset(r_queries, 0, sizeof(r_queries));
2899 r_qwskincache = NULL;
2900 r_qwskincache_size = 0;
2902 // clear out the r_skinframe state
2903 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2904 memset(&r_skinframe, 0, sizeof(r_skinframe));
2907 Mem_Free(r_svbsp.nodes);
2908 memset(&r_svbsp, 0, sizeof (r_svbsp));
2909 R_FreeTexturePool(&r_main_texturepool);
2910 loadingscreentexture = NULL;
2911 r_texture_blanknormalmap = NULL;
2912 r_texture_white = NULL;
2913 r_texture_grey128 = NULL;
2914 r_texture_black = NULL;
2915 r_texture_whitecube = NULL;
2916 r_texture_normalizationcube = NULL;
2917 r_texture_fogattenuation = NULL;
2918 r_texture_gammaramps = NULL;
2919 //r_texture_fogintensity = NULL;
2920 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2921 memset(&r_waterstate, 0, sizeof(r_waterstate));
2925 extern void CL_ParseEntityLump(char *entitystring);
2926 void gl_main_newmap(void)
2928 // FIXME: move this code to client
2930 char *entities, entname[MAX_QPATH];
2932 Mem_Free(r_qwskincache);
2933 r_qwskincache = NULL;
2934 r_qwskincache_size = 0;
2937 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2938 l = (int)strlen(entname) - 4;
2939 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2941 memcpy(entname + l, ".ent", 5);
2942 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2944 CL_ParseEntityLump(entities);
2949 if (cl.worldmodel->brush.entities)
2950 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2954 void GL_Main_Init(void)
2956 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2958 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2959 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2960 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2961 if (gamemode == GAME_NEHAHRA)
2963 Cvar_RegisterVariable (&gl_fogenable);
2964 Cvar_RegisterVariable (&gl_fogdensity);
2965 Cvar_RegisterVariable (&gl_fogred);
2966 Cvar_RegisterVariable (&gl_foggreen);
2967 Cvar_RegisterVariable (&gl_fogblue);
2968 Cvar_RegisterVariable (&gl_fogstart);
2969 Cvar_RegisterVariable (&gl_fogend);
2970 Cvar_RegisterVariable (&gl_skyclip);
2972 Cvar_RegisterVariable(&r_motionblur);
2973 Cvar_RegisterVariable(&r_motionblur_maxblur);
2974 Cvar_RegisterVariable(&r_motionblur_bmin);
2975 Cvar_RegisterVariable(&r_motionblur_vmin);
2976 Cvar_RegisterVariable(&r_motionblur_vmax);
2977 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2978 Cvar_RegisterVariable(&r_motionblur_randomize);
2979 Cvar_RegisterVariable(&r_damageblur);
2980 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
2981 Cvar_RegisterVariable(&r_equalize_entities_minambient);
2982 Cvar_RegisterVariable(&r_equalize_entities_by);
2983 Cvar_RegisterVariable(&r_equalize_entities_to);
2984 Cvar_RegisterVariable(&r_animcache);
2985 Cvar_RegisterVariable(&r_depthfirst);
2986 Cvar_RegisterVariable(&r_useinfinitefarclip);
2987 Cvar_RegisterVariable(&r_nearclip);
2988 Cvar_RegisterVariable(&r_showbboxes);
2989 Cvar_RegisterVariable(&r_showsurfaces);
2990 Cvar_RegisterVariable(&r_showtris);
2991 Cvar_RegisterVariable(&r_shownormals);
2992 Cvar_RegisterVariable(&r_showlighting);
2993 Cvar_RegisterVariable(&r_showshadowvolumes);
2994 Cvar_RegisterVariable(&r_showcollisionbrushes);
2995 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2996 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2997 Cvar_RegisterVariable(&r_showdisabledepthtest);
2998 Cvar_RegisterVariable(&r_drawportals);
2999 Cvar_RegisterVariable(&r_drawentities);
3000 Cvar_RegisterVariable(&r_cullentities_trace);
3001 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3002 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3003 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3004 Cvar_RegisterVariable(&r_drawviewmodel);
3005 Cvar_RegisterVariable(&r_speeds);
3006 Cvar_RegisterVariable(&r_fullbrights);
3007 Cvar_RegisterVariable(&r_wateralpha);
3008 Cvar_RegisterVariable(&r_dynamic);
3009 Cvar_RegisterVariable(&r_fullbright);
3010 Cvar_RegisterVariable(&r_shadows);
3011 Cvar_RegisterVariable(&r_shadows_darken);
3012 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3013 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3014 Cvar_RegisterVariable(&r_shadows_throwdistance);
3015 Cvar_RegisterVariable(&r_shadows_throwdirection);
3016 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3017 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3018 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3019 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3020 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3021 Cvar_RegisterVariable(&r_fog_exp2);
3022 Cvar_RegisterVariable(&r_drawfog);
3023 Cvar_RegisterVariable(&r_textureunits);
3024 Cvar_RegisterVariable(&r_glsl);
3025 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3026 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3027 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3028 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3029 Cvar_RegisterVariable(&r_glsl_postprocess);
3030 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3031 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3032 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3033 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3034 Cvar_RegisterVariable(&r_glsl_usegeneric);
3035 Cvar_RegisterVariable(&r_water);
3036 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3037 Cvar_RegisterVariable(&r_water_clippingplanebias);
3038 Cvar_RegisterVariable(&r_water_refractdistort);
3039 Cvar_RegisterVariable(&r_water_reflectdistort);
3040 Cvar_RegisterVariable(&r_lerpsprites);
3041 Cvar_RegisterVariable(&r_lerpmodels);
3042 Cvar_RegisterVariable(&r_lerplightstyles);
3043 Cvar_RegisterVariable(&r_waterscroll);
3044 Cvar_RegisterVariable(&r_bloom);
3045 Cvar_RegisterVariable(&r_bloom_colorscale);
3046 Cvar_RegisterVariable(&r_bloom_brighten);
3047 Cvar_RegisterVariable(&r_bloom_blur);
3048 Cvar_RegisterVariable(&r_bloom_resolution);
3049 Cvar_RegisterVariable(&r_bloom_colorexponent);
3050 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3051 Cvar_RegisterVariable(&r_hdr);
3052 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3053 Cvar_RegisterVariable(&r_hdr_glowintensity);
3054 Cvar_RegisterVariable(&r_hdr_range);
3055 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3056 Cvar_RegisterVariable(&developer_texturelogging);
3057 Cvar_RegisterVariable(&gl_lightmaps);
3058 Cvar_RegisterVariable(&r_test);
3059 Cvar_RegisterVariable(&r_batchmode);
3060 Cvar_RegisterVariable(&r_glsl_saturation);
3061 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3062 Cvar_SetValue("r_fullbrights", 0);
3063 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3065 Cvar_RegisterVariable(&r_track_sprites);
3066 Cvar_RegisterVariable(&r_track_sprites_flags);
3067 Cvar_RegisterVariable(&r_track_sprites_scalew);
3068 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3071 extern void R_Textures_Init(void);
3072 extern void GL_Draw_Init(void);
3073 extern void GL_Main_Init(void);
3074 extern void R_Shadow_Init(void);
3075 extern void R_Sky_Init(void);
3076 extern void GL_Surf_Init(void);
3077 extern void R_Particles_Init(void);
3078 extern void R_Explosion_Init(void);
3079 extern void gl_backend_init(void);
3080 extern void Sbar_Init(void);
3081 extern void R_LightningBeams_Init(void);
3082 extern void Mod_RenderInit(void);
3084 void Render_Init(void)
3096 R_LightningBeams_Init();
3105 extern char *ENGINE_EXTENSIONS;
3108 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3109 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3110 gl_version = (const char *)qglGetString(GL_VERSION);
3111 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3115 if (!gl_platformextensions)
3116 gl_platformextensions = "";
3118 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3119 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3120 Con_Printf("GL_VERSION: %s\n", gl_version);
3121 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3122 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3124 VID_CheckExtensions();
3126 // LordHavoc: report supported extensions
3127 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3129 // clear to black (loading plaque will be seen over this)
3131 qglClearColor(0,0,0,1);CHECKGLERROR
3132 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3135 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3139 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3141 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3144 p = r_refdef.view.frustum + i;
3149 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3153 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3157 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3161 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3165 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3169 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3173 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3177 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3185 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3189 for (i = 0;i < numplanes;i++)
3196 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3200 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3204 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3208 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3212 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3216 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3220 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3224 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3232 //==================================================================================
3234 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3237 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3238 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3239 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3242 typedef struct r_animcache_entity_s
3249 qboolean wantnormals;
3250 qboolean wanttangents;
3252 r_animcache_entity_t;
3254 typedef struct r_animcache_s
3256 r_animcache_entity_t entity[MAX_EDICTS*2];
3262 static r_animcache_t r_animcachestate;
3264 void R_AnimCache_Free(void)
3267 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3269 r_animcachestate.entity[idx].maxvertices = 0;
3270 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3271 r_animcachestate.entity[idx].vertex3f = NULL;
3272 r_animcachestate.entity[idx].normal3f = NULL;
3273 r_animcachestate.entity[idx].svector3f = NULL;
3274 r_animcachestate.entity[idx].tvector3f = NULL;
3276 r_animcachestate.currentindex = 0;
3277 r_animcachestate.maxindex = 0;
3280 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3284 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3286 if (cache->maxvertices >= numvertices)
3289 // Release existing memory
3290 if (cache->vertex3f)
3291 Mem_Free(cache->vertex3f);
3293 // Pad by 1024 verts
3294 cache->maxvertices = (numvertices + 1023) & ~1023;
3295 arraySize = cache->maxvertices * 3;
3297 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3298 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3299 r_animcachestate.entity[cacheIdx].vertex3f = base;
3300 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3301 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3302 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3304 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3307 void R_AnimCache_NewFrame(void)
3311 if (r_animcache.integer && r_drawentities.integer)
3312 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3313 else if (r_animcachestate.maxindex)
3316 r_animcachestate.currentindex = 0;
3318 for (i = 0;i < r_refdef.scene.numentities;i++)
3319 r_refdef.scene.entities[i]->animcacheindex = -1;
3322 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3324 dp_model_t *model = ent->model;
3325 r_animcache_entity_t *c;
3326 // see if it's already cached this frame
3327 if (ent->animcacheindex >= 0)
3329 // add normals/tangents if needed
3330 c = r_animcachestate.entity + ent->animcacheindex;
3332 wantnormals = false;
3333 if (c->wanttangents)
3334 wanttangents = false;
3335 if (wantnormals || wanttangents)
3336 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3340 // see if this ent is worth caching
3341 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3343 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3345 // assign it a cache entry and make sure the arrays are big enough
3346 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3347 ent->animcacheindex = r_animcachestate.currentindex++;
3348 c = r_animcachestate.entity + ent->animcacheindex;
3349 c->wantnormals = wantnormals;
3350 c->wanttangents = wanttangents;
3351 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3356 void R_AnimCache_CacheVisibleEntities(void)
3359 qboolean wantnormals;
3360 qboolean wanttangents;
3362 if (!r_animcachestate.maxindex)
3365 wantnormals = !r_showsurfaces.integer;
3366 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3368 // TODO: thread this?
3370 for (i = 0;i < r_refdef.scene.numentities;i++)
3372 if (!r_refdef.viewcache.entityvisible[i])
3374 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3378 //==================================================================================
3380 static void R_View_UpdateEntityLighting (void)
3383 entity_render_t *ent;
3384 vec3_t tempdiffusenormal, avg;
3385 vec_t f, fa, fd, fdd;
3387 for (i = 0;i < r_refdef.scene.numentities;i++)
3389 ent = r_refdef.scene.entities[i];
3391 // skip unseen models
3392 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3396 if (ent->model && ent->model->brush.num_leafs)
3398 // TODO: use modellight for r_ambient settings on world?
3399 VectorSet(ent->modellight_ambient, 0, 0, 0);
3400 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3401 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3405 // fetch the lighting from the worldmodel data
3406 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));
3407 VectorClear(ent->modellight_diffuse);
3408 VectorClear(tempdiffusenormal);
3409 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3412 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3413 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3414 if(ent->flags & RENDER_EQUALIZE)
3416 // first fix up ambient lighting...
3417 if(r_equalize_entities_minambient.value > 0)
3419 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3422 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3423 if(fa < r_equalize_entities_minambient.value * fd)
3426 // fa'/fd' = minambient
3427 // fa'+0.25*fd' = fa+0.25*fd
3429 // fa' = fd' * minambient
3430 // fd'*(0.25+minambient) = fa+0.25*fd
3432 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3433 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3435 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3436 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
3437 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3438 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3443 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3445 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3446 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3449 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3450 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3451 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3457 VectorSet(ent->modellight_ambient, 1, 1, 1);
3459 // move the light direction into modelspace coordinates for lighting code
3460 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3461 if(VectorLength2(ent->modellight_lightdir) == 0)
3462 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3463 VectorNormalize(ent->modellight_lightdir);
3467 #define MAX_LINEOFSIGHTTRACES 64
3469 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3472 vec3_t boxmins, boxmaxs;
3475 dp_model_t *model = r_refdef.scene.worldmodel;
3477 if (!model || !model->brush.TraceLineOfSight)
3480 // expand the box a little
3481 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3482 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3483 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3484 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3485 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3486 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3489 VectorCopy(eye, start);
3490 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3491 if (model->brush.TraceLineOfSight(model, start, end))
3494 // try various random positions
3495 for (i = 0;i < numsamples;i++)
3497 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3498 if (model->brush.TraceLineOfSight(model, start, end))
3506 static void R_View_UpdateEntityVisible (void)
3509 entity_render_t *ent;
3511 if (!r_drawentities.integer)
3514 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3515 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3517 // worldmodel can check visibility
3518 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3519 for (i = 0;i < r_refdef.scene.numentities;i++)
3521 ent = r_refdef.scene.entities[i];
3522 if (!(ent->flags & renderimask))
3523 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)))
3524 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))
3525 r_refdef.viewcache.entityvisible[i] = true;
3527 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3529 for (i = 0;i < r_refdef.scene.numentities;i++)
3531 ent = r_refdef.scene.entities[i];
3532 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3534 if(R_CanSeeBox(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3535 ent->last_trace_visibility = realtime;
3536 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3537 r_refdef.viewcache.entityvisible[i] = 0;
3544 // no worldmodel or it can't check visibility
3545 for (i = 0;i < r_refdef.scene.numentities;i++)
3547 ent = r_refdef.scene.entities[i];
3548 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));
3553 /// only used if skyrendermasked, and normally returns false
3554 int R_DrawBrushModelsSky (void)
3557 entity_render_t *ent;
3559 if (!r_drawentities.integer)
3563 for (i = 0;i < r_refdef.scene.numentities;i++)
3565 if (!r_refdef.viewcache.entityvisible[i])
3567 ent = r_refdef.scene.entities[i];
3568 if (!ent->model || !ent->model->DrawSky)
3570 ent->model->DrawSky(ent);
3576 static void R_DrawNoModel(entity_render_t *ent);
3577 static void R_DrawModels(void)
3580 entity_render_t *ent;
3582 if (!r_drawentities.integer)
3585 for (i = 0;i < r_refdef.scene.numentities;i++)
3587 if (!r_refdef.viewcache.entityvisible[i])
3589 ent = r_refdef.scene.entities[i];
3590 r_refdef.stats.entities++;
3591 if (ent->model && ent->model->Draw != NULL)
3592 ent->model->Draw(ent);
3598 static void R_DrawModelsDepth(void)
3601 entity_render_t *ent;
3603 if (!r_drawentities.integer)
3606 for (i = 0;i < r_refdef.scene.numentities;i++)
3608 if (!r_refdef.viewcache.entityvisible[i])
3610 ent = r_refdef.scene.entities[i];
3611 if (ent->model && ent->model->DrawDepth != NULL)
3612 ent->model->DrawDepth(ent);
3616 static void R_DrawModelsDebug(void)
3619 entity_render_t *ent;
3621 if (!r_drawentities.integer)
3624 for (i = 0;i < r_refdef.scene.numentities;i++)
3626 if (!r_refdef.viewcache.entityvisible[i])
3628 ent = r_refdef.scene.entities[i];
3629 if (ent->model && ent->model->DrawDebug != NULL)
3630 ent->model->DrawDebug(ent);
3634 static void R_DrawModelsAddWaterPlanes(void)
3637 entity_render_t *ent;
3639 if (!r_drawentities.integer)
3642 for (i = 0;i < r_refdef.scene.numentities;i++)
3644 if (!r_refdef.viewcache.entityvisible[i])
3646 ent = r_refdef.scene.entities[i];
3647 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3648 ent->model->DrawAddWaterPlanes(ent);
3652 static void R_DrawModelDecals_Entity(entity_render_t *ent);
3653 static void R_DrawModelDecals(void)
3656 entity_render_t *ent;
3658 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
3660 if (!r_drawentities.integer || r_showsurfaces.integer)
3663 for (i = 0;i < r_refdef.scene.numentities;i++)
3665 if (!r_refdef.viewcache.entityvisible[i])
3667 ent = r_refdef.scene.entities[i];
3668 r_refdef.stats.entities++;
3669 if (ent->decalsystem.numdecals)
3670 R_DrawModelDecals_Entity(ent);
3674 static void R_View_SetFrustum(void)
3677 double slopex, slopey;
3678 vec3_t forward, left, up, origin;
3680 // we can't trust r_refdef.view.forward and friends in reflected scenes
3681 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3684 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3685 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3686 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3687 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3688 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3689 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3690 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3691 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3692 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3693 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3694 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3695 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3699 zNear = r_refdef.nearclip;
3700 nudge = 1.0 - 1.0 / (1<<23);
3701 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3702 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3703 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3704 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3705 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3706 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3707 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3708 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3714 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3715 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3716 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3717 r_refdef.view.frustum[0].dist = m[15] - m[12];
3719 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3720 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3721 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3722 r_refdef.view.frustum[1].dist = m[15] + m[12];
3724 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3725 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3726 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3727 r_refdef.view.frustum[2].dist = m[15] - m[13];
3729 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3730 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3731 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3732 r_refdef.view.frustum[3].dist = m[15] + m[13];
3734 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3735 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3736 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3737 r_refdef.view.frustum[4].dist = m[15] - m[14];
3739 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3740 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3741 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3742 r_refdef.view.frustum[5].dist = m[15] + m[14];
3745 if (r_refdef.view.useperspective)
3747 slopex = 1.0 / r_refdef.view.frustum_x;
3748 slopey = 1.0 / r_refdef.view.frustum_y;
3749 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3750 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3751 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3752 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3753 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3755 // Leaving those out was a mistake, those were in the old code, and they
3756 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3757 // I couldn't reproduce it after adding those normalizations. --blub
3758 VectorNormalize(r_refdef.view.frustum[0].normal);
3759 VectorNormalize(r_refdef.view.frustum[1].normal);
3760 VectorNormalize(r_refdef.view.frustum[2].normal);
3761 VectorNormalize(r_refdef.view.frustum[3].normal);
3763 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3764 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]);
3765 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]);
3766 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]);
3767 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]);
3769 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3770 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3771 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3772 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3773 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3777 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3778 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3779 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3780 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3781 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3782 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3783 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3784 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3785 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3786 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3788 r_refdef.view.numfrustumplanes = 5;
3790 if (r_refdef.view.useclipplane)
3792 r_refdef.view.numfrustumplanes = 6;
3793 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3796 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3797 PlaneClassify(r_refdef.view.frustum + i);
3799 // LordHavoc: note to all quake engine coders, Quake had a special case
3800 // for 90 degrees which assumed a square view (wrong), so I removed it,
3801 // Quake2 has it disabled as well.
3803 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3804 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3805 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3806 //PlaneClassify(&frustum[0]);
3808 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3809 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3810 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3811 //PlaneClassify(&frustum[1]);
3813 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3814 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3815 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3816 //PlaneClassify(&frustum[2]);
3818 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3819 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3820 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3821 //PlaneClassify(&frustum[3]);
3824 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3825 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3826 //PlaneClassify(&frustum[4]);
3829 void R_View_Update(void)
3831 R_View_SetFrustum();
3832 R_View_WorldVisibility(r_refdef.view.useclipplane);
3833 R_View_UpdateEntityVisible();
3834 R_View_UpdateEntityLighting();
3837 void R_SetupView(qboolean allowwaterclippingplane)
3839 const double *customclipplane = NULL;
3841 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3843 // LordHavoc: couldn't figure out how to make this approach the
3844 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3845 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3846 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3847 dist = r_refdef.view.clipplane.dist;
3848 plane[0] = r_refdef.view.clipplane.normal[0];
3849 plane[1] = r_refdef.view.clipplane.normal[1];
3850 plane[2] = r_refdef.view.clipplane.normal[2];
3852 customclipplane = plane;
3855 if (!r_refdef.view.useperspective)
3856 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);
3857 else if (gl_stencil && r_useinfinitefarclip.integer)
3858 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);
3860 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);
3861 R_SetViewport(&r_refdef.view.viewport);
3864 void R_ResetViewRendering2D(void)
3866 r_viewport_t viewport;
3869 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3870 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);
3871 R_SetViewport(&viewport);
3872 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3873 GL_Color(1, 1, 1, 1);
3874 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3875 GL_BlendFunc(GL_ONE, GL_ZERO);
3876 GL_AlphaTest(false);
3877 GL_ScissorTest(false);
3878 GL_DepthMask(false);
3879 GL_DepthRange(0, 1);
3880 GL_DepthTest(false);
3881 R_Mesh_Matrix(&identitymatrix);
3882 R_Mesh_ResetTextureState();
3883 GL_PolygonOffset(0, 0);
3884 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3885 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3886 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3887 qglStencilMask(~0);CHECKGLERROR
3888 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3889 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3890 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3891 R_SetupGenericShader(true);
3894 void R_ResetViewRendering3D(void)
3899 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3900 GL_Color(1, 1, 1, 1);
3901 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3902 GL_BlendFunc(GL_ONE, GL_ZERO);
3903 GL_AlphaTest(false);
3904 GL_ScissorTest(true);
3906 GL_DepthRange(0, 1);
3908 R_Mesh_Matrix(&identitymatrix);
3909 R_Mesh_ResetTextureState();
3910 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3911 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3912 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3913 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3914 qglStencilMask(~0);CHECKGLERROR
3915 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3916 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3917 GL_CullFace(r_refdef.view.cullface_back);
3918 R_SetupGenericShader(true);
3921 void R_RenderScene(void);
3922 void R_RenderWaterPlanes(void);
3924 static void R_Water_StartFrame(void)
3927 int waterwidth, waterheight, texturewidth, textureheight;
3928 r_waterstate_waterplane_t *p;
3930 // set waterwidth and waterheight to the water resolution that will be
3931 // used (often less than the screen resolution for faster rendering)
3932 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3933 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3935 // calculate desired texture sizes
3936 // can't use water if the card does not support the texture size
3937 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3938 texturewidth = textureheight = waterwidth = waterheight = 0;
3939 else if (gl_support_arb_texture_non_power_of_two)
3941 texturewidth = waterwidth;
3942 textureheight = waterheight;
3946 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3947 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3950 // allocate textures as needed
3951 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3953 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3954 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3956 if (p->texture_refraction)
3957 R_FreeTexture(p->texture_refraction);
3958 p->texture_refraction = NULL;
3959 if (p->texture_reflection)
3960 R_FreeTexture(p->texture_reflection);
3961 p->texture_reflection = NULL;
3963 memset(&r_waterstate, 0, sizeof(r_waterstate));
3964 r_waterstate.texturewidth = texturewidth;
3965 r_waterstate.textureheight = textureheight;
3968 if (r_waterstate.texturewidth)
3970 r_waterstate.enabled = true;
3972 // when doing a reduced render (HDR) we want to use a smaller area
3973 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3974 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3976 // set up variables that will be used in shader setup
3977 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3978 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3979 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3980 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3983 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3984 r_waterstate.numwaterplanes = 0;
3987 void R_Water_AddWaterPlane(msurface_t *surface)
3989 int triangleindex, planeindex;
3995 r_waterstate_waterplane_t *p;
3996 texture_t *t = R_GetCurrentTexture(surface->texture);
3997 // just use the first triangle with a valid normal for any decisions
3998 VectorClear(normal);
3999 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4001 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4002 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4003 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4004 TriangleNormal(vert[0], vert[1], vert[2], normal);
4005 if (VectorLength2(normal) >= 0.001)
4009 VectorCopy(normal, plane.normal);
4010 VectorNormalize(plane.normal);
4011 plane.dist = DotProduct(vert[0], plane.normal);
4012 PlaneClassify(&plane);
4013 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4015 // skip backfaces (except if nocullface is set)
4016 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4018 VectorNegate(plane.normal, plane.normal);
4020 PlaneClassify(&plane);
4024 // find a matching plane if there is one
4025 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4026 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4028 if (planeindex >= r_waterstate.maxwaterplanes)
4029 return; // nothing we can do, out of planes
4031 // if this triangle does not fit any known plane rendered this frame, add one
4032 if (planeindex >= r_waterstate.numwaterplanes)
4034 // store the new plane
4035 r_waterstate.numwaterplanes++;
4037 // clear materialflags and pvs
4038 p->materialflags = 0;
4039 p->pvsvalid = false;
4041 // merge this surface's materialflags into the waterplane
4042 p->materialflags |= t->currentmaterialflags;
4043 // merge this surface's PVS into the waterplane
4044 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4045 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4046 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4048 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4053 static void R_Water_ProcessPlanes(void)
4055 r_refdef_view_t originalview;
4056 r_refdef_view_t myview;
4058 r_waterstate_waterplane_t *p;
4060 originalview = r_refdef.view;
4062 // make sure enough textures are allocated
4063 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4065 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4067 if (!p->texture_refraction)
4068 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);
4069 if (!p->texture_refraction)
4073 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4075 if (!p->texture_reflection)
4076 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);
4077 if (!p->texture_reflection)
4083 r_refdef.view = originalview;
4084 r_refdef.view.showdebug = false;
4085 r_refdef.view.width = r_waterstate.waterwidth;
4086 r_refdef.view.height = r_waterstate.waterheight;
4087 r_refdef.view.useclipplane = true;
4088 myview = r_refdef.view;
4089 r_waterstate.renderingscene = true;
4090 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4092 // render the normal view scene and copy into texture
4093 // (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)
4094 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4096 r_refdef.view = myview;
4097 r_refdef.view.clipplane = p->plane;
4098 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4099 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4100 PlaneClassify(&r_refdef.view.clipplane);
4102 R_ResetViewRendering3D();
4103 R_ClearScreen(r_refdef.fogenabled);
4107 // copy view into the screen texture
4108 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4109 GL_ActiveTexture(0);
4111 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
4114 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4116 r_refdef.view = myview;
4117 // render reflected scene and copy into texture
4118 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4119 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4120 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4121 r_refdef.view.clipplane = p->plane;
4122 // reverse the cullface settings for this render
4123 r_refdef.view.cullface_front = GL_FRONT;
4124 r_refdef.view.cullface_back = GL_BACK;
4125 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4127 r_refdef.view.usecustompvs = true;
4129 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4131 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4134 R_ResetViewRendering3D();
4135 R_ClearScreen(r_refdef.fogenabled);
4139 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4140 GL_ActiveTexture(0);
4142 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
4145 r_waterstate.renderingscene = false;
4146 r_refdef.view = originalview;
4147 R_ResetViewRendering3D();
4148 R_ClearScreen(r_refdef.fogenabled);
4152 r_refdef.view = originalview;
4153 r_waterstate.renderingscene = false;
4154 Cvar_SetValueQuick(&r_water, 0);
4155 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4159 void R_Bloom_StartFrame(void)
4161 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4163 // set bloomwidth and bloomheight to the bloom resolution that will be
4164 // used (often less than the screen resolution for faster rendering)
4165 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4166 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4167 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4168 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
4169 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
4171 // calculate desired texture sizes
4172 if (gl_support_arb_texture_non_power_of_two)
4174 screentexturewidth = r_refdef.view.width;
4175 screentextureheight = r_refdef.view.height;
4176 bloomtexturewidth = r_bloomstate.bloomwidth;
4177 bloomtextureheight = r_bloomstate.bloomheight;
4181 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4182 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4183 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4184 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4187 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))
4189 Cvar_SetValueQuick(&r_hdr, 0);
4190 Cvar_SetValueQuick(&r_bloom, 0);
4191 Cvar_SetValueQuick(&r_motionblur, 0);
4192 Cvar_SetValueQuick(&r_damageblur, 0);
4195 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)))
4196 screentexturewidth = screentextureheight = 0;
4197 if (!r_hdr.integer && !r_bloom.integer)
4198 bloomtexturewidth = bloomtextureheight = 0;
4200 // allocate textures as needed
4201 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4203 if (r_bloomstate.texture_screen)
4204 R_FreeTexture(r_bloomstate.texture_screen);
4205 r_bloomstate.texture_screen = NULL;
4206 r_bloomstate.screentexturewidth = screentexturewidth;
4207 r_bloomstate.screentextureheight = screentextureheight;
4208 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4209 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);
4211 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4213 if (r_bloomstate.texture_bloom)
4214 R_FreeTexture(r_bloomstate.texture_bloom);
4215 r_bloomstate.texture_bloom = NULL;
4216 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4217 r_bloomstate.bloomtextureheight = bloomtextureheight;
4218 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4219 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);
4222 // when doing a reduced render (HDR) we want to use a smaller area
4223 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4224 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4225 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4226 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4227 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4229 // set up a texcoord array for the full resolution screen image
4230 // (we have to keep this around to copy back during final render)
4231 r_bloomstate.screentexcoord2f[0] = 0;
4232 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4233 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4234 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4235 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4236 r_bloomstate.screentexcoord2f[5] = 0;
4237 r_bloomstate.screentexcoord2f[6] = 0;
4238 r_bloomstate.screentexcoord2f[7] = 0;
4240 // set up a texcoord array for the reduced resolution bloom image
4241 // (which will be additive blended over the screen image)
4242 r_bloomstate.bloomtexcoord2f[0] = 0;
4243 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4244 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4245 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4246 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4247 r_bloomstate.bloomtexcoord2f[5] = 0;
4248 r_bloomstate.bloomtexcoord2f[6] = 0;
4249 r_bloomstate.bloomtexcoord2f[7] = 0;
4251 if (r_hdr.integer || r_bloom.integer)
4253 r_bloomstate.enabled = true;
4254 r_bloomstate.hdr = r_hdr.integer != 0;
4257 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);
4260 void R_Bloom_CopyBloomTexture(float colorscale)
4262 r_refdef.stats.bloom++;
4264 // scale down screen texture to the bloom texture size
4266 R_SetViewport(&r_bloomstate.viewport);
4267 GL_BlendFunc(GL_ONE, GL_ZERO);
4268 GL_Color(colorscale, colorscale, colorscale, 1);
4269 // TODO: optimize with multitexture or GLSL
4270 R_SetupGenericShader(true);
4271 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4272 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4273 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4274 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4276 // we now have a bloom image in the framebuffer
4277 // copy it into the bloom image texture for later processing
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;
4285 void R_Bloom_CopyHDRTexture(void)
4287 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4288 GL_ActiveTexture(0);
4290 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
4291 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4294 void R_Bloom_MakeTexture(void)
4297 float xoffset, yoffset, r, brighten;
4299 r_refdef.stats.bloom++;
4301 R_ResetViewRendering2D();
4302 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4303 R_Mesh_ColorPointer(NULL, 0, 0);
4304 R_SetupGenericShader(true);
4306 // we have a bloom image in the framebuffer
4308 R_SetViewport(&r_bloomstate.viewport);
4310 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4313 r = bound(0, r_bloom_colorexponent.value / x, 1);
4314 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4315 GL_Color(r, r, r, 1);
4316 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4317 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4318 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4319 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4321 // copy the vertically blurred bloom view to a texture
4322 GL_ActiveTexture(0);
4324 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4325 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4328 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4329 brighten = r_bloom_brighten.value;
4331 brighten *= r_hdr_range.value;
4332 brighten = sqrt(brighten);
4334 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4335 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4336 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4338 for (dir = 0;dir < 2;dir++)
4340 // blend on at multiple vertical offsets to achieve a vertical blur
4341 // TODO: do offset blends using GLSL
4342 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4343 GL_BlendFunc(GL_ONE, GL_ZERO);
4344 for (x = -range;x <= range;x++)
4346 if (!dir){xoffset = 0;yoffset = x;}
4347 else {xoffset = x;yoffset = 0;}
4348 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4349 yoffset /= (float)r_bloomstate.bloomtextureheight;
4350 // compute a texcoord array with the specified x and y offset
4351 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4352 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4353 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4354 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4355 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4356 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4357 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4358 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4359 // this r value looks like a 'dot' particle, fading sharply to
4360 // black at the edges
4361 // (probably not realistic but looks good enough)
4362 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4363 //r = brighten/(range*2+1);
4364 r = brighten / (range * 2 + 1);
4366 r *= (1 - x*x/(float)(range*range));
4367 GL_Color(r, r, r, 1);
4368 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4369 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4370 GL_BlendFunc(GL_ONE, GL_ONE);
4373 // copy the vertically blurred bloom view to a texture
4374 GL_ActiveTexture(0);
4376 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4377 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4380 // apply subtract last
4381 // (just like it would be in a GLSL shader)
4382 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4384 GL_BlendFunc(GL_ONE, GL_ZERO);
4385 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4386 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4387 GL_Color(1, 1, 1, 1);
4388 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4389 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4391 GL_BlendFunc(GL_ONE, GL_ONE);
4392 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4393 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4394 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4395 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4396 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4397 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4398 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4400 // copy the darkened bloom view to a texture
4401 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4402 GL_ActiveTexture(0);
4404 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4405 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4409 void R_HDR_RenderBloomTexture(void)
4411 int oldwidth, oldheight;
4412 float oldcolorscale;
4414 oldcolorscale = r_refdef.view.colorscale;
4415 oldwidth = r_refdef.view.width;
4416 oldheight = r_refdef.view.height;
4417 r_refdef.view.width = r_bloomstate.bloomwidth;
4418 r_refdef.view.height = r_bloomstate.bloomheight;
4420 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4421 // TODO: add exposure compensation features
4422 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4424 r_refdef.view.showdebug = false;
4425 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4427 R_ResetViewRendering3D();
4429 R_ClearScreen(r_refdef.fogenabled);
4430 if (r_timereport_active)
4431 R_TimeReport("HDRclear");
4434 if (r_timereport_active)
4435 R_TimeReport("visibility");
4437 // only do secondary renders with HDR if r_hdr is 2 or higher
4438 r_waterstate.numwaterplanes = 0;
4439 if (r_waterstate.enabled && r_hdr.integer >= 2)
4440 R_RenderWaterPlanes();
4442 r_refdef.view.showdebug = true;
4444 r_waterstate.numwaterplanes = 0;
4446 R_ResetViewRendering2D();
4448 R_Bloom_CopyHDRTexture();
4449 R_Bloom_MakeTexture();
4451 // restore the view settings
4452 r_refdef.view.width = oldwidth;
4453 r_refdef.view.height = oldheight;
4454 r_refdef.view.colorscale = oldcolorscale;
4456 R_ResetViewRendering3D();
4458 R_ClearScreen(r_refdef.fogenabled);
4459 if (r_timereport_active)
4460 R_TimeReport("viewclear");
4463 static void R_BlendView(void)
4465 if (r_bloomstate.texture_screen)
4467 // make sure the buffer is available
4468 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4470 R_ResetViewRendering2D();
4471 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4472 R_Mesh_ColorPointer(NULL, 0, 0);
4473 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4474 GL_ActiveTexture(0);CHECKGLERROR
4476 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4478 // declare variables
4480 static float avgspeed;
4482 speed = VectorLength(cl.movement_velocity);
4484 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4485 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4487 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4488 speed = bound(0, speed, 1);
4489 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4491 // calculate values into a standard alpha
4492 cl.motionbluralpha = 1 - exp(-
4494 (r_motionblur.value * speed / 80)
4496 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4499 max(0.0001, cl.time - cl.oldtime) // fps independent
4502 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4503 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4505 if (cl.motionbluralpha > 0)
4507 R_SetupGenericShader(true);
4508 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4509 GL_Color(1, 1, 1, cl.motionbluralpha);
4510 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4511 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4512 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4513 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4517 // copy view into the screen texture
4518 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
4519 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4522 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4524 unsigned int permutation =
4525 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4526 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4527 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4528 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4529 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4531 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4533 // render simple bloom effect
4534 // copy the screen and shrink it and darken it for the bloom process
4535 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4536 // make the bloom texture
4537 R_Bloom_MakeTexture();
4540 R_ResetViewRendering2D();
4541 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4542 R_Mesh_ColorPointer(NULL, 0, 0);
4543 GL_Color(1, 1, 1, 1);
4544 GL_BlendFunc(GL_ONE, GL_ZERO);
4545 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4546 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4547 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4548 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4549 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4550 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4551 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4552 if (r_glsl_permutation->loc_TintColor >= 0)
4553 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4554 if (r_glsl_permutation->loc_ClientTime >= 0)
4555 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4556 if (r_glsl_permutation->loc_PixelSize >= 0)
4557 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4558 if (r_glsl_permutation->loc_UserVec1 >= 0)
4560 float a=0, b=0, c=0, d=0;
4561 #if _MSC_VER >= 1400
4562 #define sscanf sscanf_s
4564 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4565 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4567 if (r_glsl_permutation->loc_UserVec2 >= 0)
4569 float a=0, b=0, c=0, d=0;
4570 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4571 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4573 if (r_glsl_permutation->loc_UserVec3 >= 0)
4575 float a=0, b=0, c=0, d=0;
4576 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4577 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4579 if (r_glsl_permutation->loc_UserVec4 >= 0)
4581 float a=0, b=0, c=0, d=0;
4582 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4583 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4585 if (r_glsl_permutation->loc_Saturation >= 0)
4586 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4587 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4588 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4594 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4596 // render high dynamic range bloom effect
4597 // the bloom texture was made earlier this render, so we just need to
4598 // blend it onto the screen...
4599 R_ResetViewRendering2D();
4600 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4601 R_Mesh_ColorPointer(NULL, 0, 0);
4602 R_SetupGenericShader(true);
4603 GL_Color(1, 1, 1, 1);
4604 GL_BlendFunc(GL_ONE, GL_ONE);
4605 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4606 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4607 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4608 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4610 else if (r_bloomstate.texture_bloom)
4612 // render simple bloom effect
4613 // copy the screen and shrink it and darken it for the bloom process
4614 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4615 // make the bloom texture
4616 R_Bloom_MakeTexture();
4617 // put the original screen image back in place and blend the bloom
4619 R_ResetViewRendering2D();
4620 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4621 R_Mesh_ColorPointer(NULL, 0, 0);
4622 GL_Color(1, 1, 1, 1);
4623 GL_BlendFunc(GL_ONE, GL_ZERO);
4624 // do both in one pass if possible
4625 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4626 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4627 if (r_textureunits.integer >= 2 && gl_combine.integer)
4629 R_SetupGenericTwoTextureShader(GL_ADD);
4630 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4631 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4635 R_SetupGenericShader(true);
4636 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4637 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4638 // now blend on the bloom texture
4639 GL_BlendFunc(GL_ONE, GL_ONE);
4640 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4641 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4643 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4644 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4646 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4648 // apply a color tint to the whole view
4649 R_ResetViewRendering2D();
4650 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4651 R_Mesh_ColorPointer(NULL, 0, 0);
4652 R_SetupGenericShader(false);
4653 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4654 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4655 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4659 matrix4x4_t r_waterscrollmatrix;
4661 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4663 if (r_refdef.fog_density)
4665 r_refdef.fogcolor[0] = r_refdef.fog_red;
4666 r_refdef.fogcolor[1] = r_refdef.fog_green;
4667 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4669 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4670 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4671 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4672 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4676 VectorCopy(r_refdef.fogcolor, fogvec);
4677 // color.rgb *= ContrastBoost * SceneBrightness;
4678 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4679 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4680 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4681 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4686 void R_UpdateVariables(void)
4690 r_refdef.scene.ambient = r_ambient.value;
4692 r_refdef.farclip = 4096;
4693 if (r_refdef.scene.worldmodel)
4694 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4695 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4697 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4698 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4699 r_refdef.polygonfactor = 0;
4700 r_refdef.polygonoffset = 0;
4701 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4702 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4704 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4705 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4706 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4707 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4708 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4709 if (r_showsurfaces.integer)
4711 r_refdef.scene.rtworld = false;
4712 r_refdef.scene.rtworldshadows = false;
4713 r_refdef.scene.rtdlight = false;
4714 r_refdef.scene.rtdlightshadows = false;
4715 r_refdef.lightmapintensity = 0;
4718 if (gamemode == GAME_NEHAHRA)
4720 if (gl_fogenable.integer)
4722 r_refdef.oldgl_fogenable = true;
4723 r_refdef.fog_density = gl_fogdensity.value;
4724 r_refdef.fog_red = gl_fogred.value;
4725 r_refdef.fog_green = gl_foggreen.value;
4726 r_refdef.fog_blue = gl_fogblue.value;
4727 r_refdef.fog_alpha = 1;
4728 r_refdef.fog_start = 0;
4729 r_refdef.fog_end = gl_skyclip.value;
4730 r_refdef.fog_height = 1<<30;
4731 r_refdef.fog_fadedepth = 128;
4733 else if (r_refdef.oldgl_fogenable)
4735 r_refdef.oldgl_fogenable = false;
4736 r_refdef.fog_density = 0;
4737 r_refdef.fog_red = 0;
4738 r_refdef.fog_green = 0;
4739 r_refdef.fog_blue = 0;
4740 r_refdef.fog_alpha = 0;
4741 r_refdef.fog_start = 0;
4742 r_refdef.fog_end = 0;
4743 r_refdef.fog_height = 1<<30;
4744 r_refdef.fog_fadedepth = 128;
4748 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4749 r_refdef.fog_start = max(0, r_refdef.fog_start);
4750 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4752 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4754 if (r_refdef.fog_density && r_drawfog.integer)
4756 r_refdef.fogenabled = true;
4757 // this is the point where the fog reaches 0.9986 alpha, which we
4758 // consider a good enough cutoff point for the texture
4759 // (0.9986 * 256 == 255.6)
4760 if (r_fog_exp2.integer)
4761 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4763 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4764 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4765 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4766 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4767 // fog color was already set
4768 // update the fog texture
4769 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)
4770 R_BuildFogTexture();
4773 r_refdef.fogenabled = false;
4775 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4777 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4779 // build GLSL gamma texture
4780 #define RAMPWIDTH 256
4781 unsigned short ramp[RAMPWIDTH * 3];
4782 unsigned char rampbgr[RAMPWIDTH][4];
4785 r_texture_gammaramps_serial = vid_gammatables_serial;
4787 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4788 for(i = 0; i < RAMPWIDTH; ++i)
4790 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4791 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4792 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4795 if (r_texture_gammaramps)
4797 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4801 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);
4807 // remove GLSL gamma texture
4811 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4812 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4818 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4819 if( scenetype != r_currentscenetype ) {
4820 // store the old scenetype
4821 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4822 r_currentscenetype = scenetype;
4823 // move in the new scene
4824 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4833 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4835 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4836 if( scenetype == r_currentscenetype ) {
4837 return &r_refdef.scene;
4839 return &r_scenes_store[ scenetype ];
4848 void R_RenderView(void)
4850 if (r_timereport_active)
4851 R_TimeReport("start");
4852 r_frame++; // used only by R_GetCurrentTexture
4853 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4855 R_AnimCache_NewFrame();
4857 if (r_refdef.view.isoverlay)
4859 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4860 GL_Clear( GL_DEPTH_BUFFER_BIT );
4861 R_TimeReport("depthclear");
4863 r_refdef.view.showdebug = false;
4865 r_waterstate.enabled = false;
4866 r_waterstate.numwaterplanes = 0;
4874 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4875 return; //Host_Error ("R_RenderView: NULL worldmodel");
4877 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4879 // break apart the view matrix into vectors for various purposes
4880 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4881 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4882 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4883 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4884 // make an inverted copy of the view matrix for tracking sprites
4885 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4887 R_Shadow_UpdateWorldLightSelection();
4889 R_Bloom_StartFrame();
4890 R_Water_StartFrame();
4893 if (r_timereport_active)
4894 R_TimeReport("viewsetup");
4896 R_ResetViewRendering3D();
4898 if (r_refdef.view.clear || r_refdef.fogenabled)
4900 R_ClearScreen(r_refdef.fogenabled);
4901 if (r_timereport_active)
4902 R_TimeReport("viewclear");
4904 r_refdef.view.clear = true;
4906 // this produces a bloom texture to be used in R_BlendView() later
4908 R_HDR_RenderBloomTexture();
4910 r_refdef.view.showdebug = true;
4913 if (r_timereport_active)
4914 R_TimeReport("visibility");
4916 r_waterstate.numwaterplanes = 0;
4917 if (r_waterstate.enabled)
4918 R_RenderWaterPlanes();
4921 r_waterstate.numwaterplanes = 0;
4924 if (r_timereport_active)
4925 R_TimeReport("blendview");
4927 GL_Scissor(0, 0, vid.width, vid.height);
4928 GL_ScissorTest(false);
4932 void R_RenderWaterPlanes(void)
4934 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4936 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4937 if (r_timereport_active)
4938 R_TimeReport("waterworld");
4941 // don't let sound skip if going slow
4942 if (r_refdef.scene.extraupdate)
4945 R_DrawModelsAddWaterPlanes();
4946 if (r_timereport_active)
4947 R_TimeReport("watermodels");
4949 if (r_waterstate.numwaterplanes)
4951 R_Water_ProcessPlanes();
4952 if (r_timereport_active)
4953 R_TimeReport("waterscenes");
4957 extern void R_DrawLightningBeams (void);
4958 extern void VM_CL_AddPolygonsToMeshQueue (void);
4959 extern void R_DrawPortals (void);
4960 extern cvar_t cl_locs_show;
4961 static void R_DrawLocs(void);
4962 static void R_DrawEntityBBoxes(void);
4963 extern cvar_t cl_decals_newsystem;
4964 void R_RenderScene(void)
4966 r_refdef.stats.renders++;
4970 // don't let sound skip if going slow
4971 if (r_refdef.scene.extraupdate)
4974 R_MeshQueue_BeginScene();
4978 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);
4980 if (cl.csqc_vidvars.drawworld)
4982 // don't let sound skip if going slow
4983 if (r_refdef.scene.extraupdate)
4986 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4988 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4989 if (r_timereport_active)
4990 R_TimeReport("worldsky");
4993 if (R_DrawBrushModelsSky() && r_timereport_active)
4994 R_TimeReport("bmodelsky");
4996 if (skyrendermasked && skyrenderlater)
4998 // we have to force off the water clipping plane while rendering sky
5005 R_AnimCache_CacheVisibleEntities();
5007 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5009 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5010 if (r_timereport_active)
5011 R_TimeReport("worlddepth");
5013 if (r_depthfirst.integer >= 2)
5015 R_DrawModelsDepth();
5016 if (r_timereport_active)
5017 R_TimeReport("modeldepth");
5020 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5022 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5023 if (r_timereport_active)
5024 R_TimeReport("world");
5027 // don't let sound skip if going slow
5028 if (r_refdef.scene.extraupdate)
5032 if (r_timereport_active)
5033 R_TimeReport("models");
5035 // don't let sound skip if going slow
5036 if (r_refdef.scene.extraupdate)
5039 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5041 R_DrawModelShadows();
5042 R_ResetViewRendering3D();
5043 // don't let sound skip if going slow
5044 if (r_refdef.scene.extraupdate)
5048 R_ShadowVolumeLighting(false);
5049 if (r_timereport_active)
5050 R_TimeReport("rtlights");
5052 // don't let sound skip if going slow
5053 if (r_refdef.scene.extraupdate)
5056 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5058 R_DrawModelShadows();
5059 R_ResetViewRendering3D();
5060 // don't let sound skip if going slow
5061 if (r_refdef.scene.extraupdate)
5065 if (cl.csqc_vidvars.drawworld)
5067 if (cl_decals_newsystem.integer)
5069 R_DrawModelDecals();
5070 if (r_timereport_active)
5071 R_TimeReport("modeldecals");
5076 if (r_timereport_active)
5077 R_TimeReport("decals");
5081 if (r_timereport_active)
5082 R_TimeReport("particles");
5085 if (r_timereport_active)
5086 R_TimeReport("explosions");
5088 R_DrawLightningBeams();
5089 if (r_timereport_active)
5090 R_TimeReport("lightning");
5093 R_SetupGenericShader(true);
5094 VM_CL_AddPolygonsToMeshQueue();
5096 if (r_refdef.view.showdebug)
5098 if (cl_locs_show.integer)
5101 if (r_timereport_active)
5102 R_TimeReport("showlocs");
5105 if (r_drawportals.integer)
5108 if (r_timereport_active)
5109 R_TimeReport("portals");
5112 if (r_showbboxes.value > 0)
5114 R_DrawEntityBBoxes();
5115 if (r_timereport_active)
5116 R_TimeReport("bboxes");
5120 R_SetupGenericShader(true);
5121 R_MeshQueue_RenderTransparent();
5122 if (r_timereport_active)
5123 R_TimeReport("drawtrans");
5125 R_SetupGenericShader(true);
5127 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))
5129 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5130 if (r_timereport_active)
5131 R_TimeReport("worlddebug");
5132 R_DrawModelsDebug();
5133 if (r_timereport_active)
5134 R_TimeReport("modeldebug");
5137 R_SetupGenericShader(true);
5139 if (cl.csqc_vidvars.drawworld)
5142 if (r_timereport_active)
5143 R_TimeReport("coronas");
5146 // don't let sound skip if going slow
5147 if (r_refdef.scene.extraupdate)
5150 R_ResetViewRendering2D();
5153 static const unsigned short bboxelements[36] =
5163 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5166 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5168 RSurf_ActiveWorldEntity();
5170 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5171 GL_DepthMask(false);
5172 GL_DepthRange(0, 1);
5173 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5174 R_Mesh_ResetTextureState();
5176 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5177 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5178 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5179 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5180 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5181 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5182 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5183 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5184 R_FillColors(color4f, 8, cr, cg, cb, ca);
5185 if (r_refdef.fogenabled)
5187 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5189 f1 = RSurf_FogVertex(v);
5191 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5192 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5193 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5196 R_Mesh_VertexPointer(vertex3f, 0, 0);
5197 R_Mesh_ColorPointer(color4f, 0, 0);
5198 R_Mesh_ResetTextureState();
5199 R_SetupGenericShader(false);
5200 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5203 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5207 prvm_edict_t *edict;
5208 prvm_prog_t *prog_save = prog;
5210 // this function draws bounding boxes of server entities
5214 GL_CullFace(GL_NONE);
5215 R_SetupGenericShader(false);
5219 for (i = 0;i < numsurfaces;i++)
5221 edict = PRVM_EDICT_NUM(surfacelist[i]);
5222 switch ((int)edict->fields.server->solid)
5224 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5225 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5226 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5227 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5228 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5229 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5231 color[3] *= r_showbboxes.value;
5232 color[3] = bound(0, color[3], 1);
5233 GL_DepthTest(!r_showdisabledepthtest.integer);
5234 GL_CullFace(r_refdef.view.cullface_front);
5235 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5241 static void R_DrawEntityBBoxes(void)
5244 prvm_edict_t *edict;
5246 prvm_prog_t *prog_save = prog;
5248 // this function draws bounding boxes of server entities
5254 for (i = 0;i < prog->num_edicts;i++)
5256 edict = PRVM_EDICT_NUM(i);
5257 if (edict->priv.server->free)
5259 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5260 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5262 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5264 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5265 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5271 static const int nomodelelement3i[24] =
5283 static const unsigned short nomodelelement3s[24] =
5295 static const float nomodelvertex3f[6*3] =
5305 static const float nomodelcolor4f[6*4] =
5307 0.0f, 0.0f, 0.5f, 1.0f,
5308 0.0f, 0.0f, 0.5f, 1.0f,
5309 0.0f, 0.5f, 0.0f, 1.0f,
5310 0.0f, 0.5f, 0.0f, 1.0f,
5311 0.5f, 0.0f, 0.0f, 1.0f,
5312 0.5f, 0.0f, 0.0f, 1.0f
5315 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5321 RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
5323 // this is only called once per entity so numsurfaces is always 1, and
5324 // surfacelist is always {0}, so this code does not handle batches
5326 if (rsurface.ent_flags & RENDER_ADDITIVE)
5328 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5329 GL_DepthMask(false);
5331 else if (rsurface.ent_color[3] < 1)
5333 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5334 GL_DepthMask(false);
5338 GL_BlendFunc(GL_ONE, GL_ZERO);
5341 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5342 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5343 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5344 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5345 R_SetupGenericShader(false);
5346 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5347 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5348 R_Mesh_ColorPointer(color4f, 0, 0);
5349 for (i = 0, c = color4f;i < 6;i++, c += 4)
5351 c[0] *= rsurface.ent_color[0];
5352 c[1] *= rsurface.ent_color[1];
5353 c[2] *= rsurface.ent_color[2];
5354 c[3] *= rsurface.ent_color[3];
5356 if (r_refdef.fogenabled)
5358 for (i = 0, c = color4f;i < 6;i++, c += 4)
5360 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5362 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5363 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5364 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5367 R_Mesh_ResetTextureState();
5368 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5371 void R_DrawNoModel(entity_render_t *ent)
5374 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5375 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5376 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5378 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5381 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5383 vec3_t right1, right2, diff, normal;
5385 VectorSubtract (org2, org1, normal);
5387 // calculate 'right' vector for start
5388 VectorSubtract (r_refdef.view.origin, org1, diff);
5389 CrossProduct (normal, diff, right1);
5390 VectorNormalize (right1);
5392 // calculate 'right' vector for end
5393 VectorSubtract (r_refdef.view.origin, org2, diff);
5394 CrossProduct (normal, diff, right2);
5395 VectorNormalize (right2);
5397 vert[ 0] = org1[0] + width * right1[0];
5398 vert[ 1] = org1[1] + width * right1[1];
5399 vert[ 2] = org1[2] + width * right1[2];
5400 vert[ 3] = org1[0] - width * right1[0];
5401 vert[ 4] = org1[1] - width * right1[1];
5402 vert[ 5] = org1[2] - width * right1[2];
5403 vert[ 6] = org2[0] - width * right2[0];
5404 vert[ 7] = org2[1] - width * right2[1];
5405 vert[ 8] = org2[2] - width * right2[2];
5406 vert[ 9] = org2[0] + width * right2[0];
5407 vert[10] = org2[1] + width * right2[1];
5408 vert[11] = org2[2] + width * right2[2];
5411 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
5413 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5414 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5415 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5416 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5417 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5418 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5419 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5420 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5421 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5422 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5423 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5424 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5427 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5432 VectorSet(v, x, y, z);
5433 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5434 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5436 if (i == mesh->numvertices)
5438 if (mesh->numvertices < mesh->maxvertices)
5440 VectorCopy(v, vertex3f);
5441 mesh->numvertices++;
5443 return mesh->numvertices;
5449 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5453 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5454 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5455 e = mesh->element3i + mesh->numtriangles * 3;
5456 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5458 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5459 if (mesh->numtriangles < mesh->maxtriangles)
5464 mesh->numtriangles++;
5466 element[1] = element[2];
5470 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5474 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5475 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5476 e = mesh->element3i + mesh->numtriangles * 3;
5477 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5479 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5480 if (mesh->numtriangles < mesh->maxtriangles)
5485 mesh->numtriangles++;
5487 element[1] = element[2];
5491 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5492 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5494 int planenum, planenum2;
5497 mplane_t *plane, *plane2;
5499 double temppoints[2][256*3];
5500 // figure out how large a bounding box we need to properly compute this brush
5502 for (w = 0;w < numplanes;w++)
5503 maxdist = max(maxdist, fabs(planes[w].dist));
5504 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5505 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5506 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5510 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5511 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5513 if (planenum2 == planenum)
5515 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);
5518 if (tempnumpoints < 3)
5520 // generate elements forming a triangle fan for this polygon
5521 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5525 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)
5527 texturelayer_t *layer;
5528 layer = t->currentlayers + t->currentnumlayers++;
5530 layer->depthmask = depthmask;
5531 layer->blendfunc1 = blendfunc1;
5532 layer->blendfunc2 = blendfunc2;
5533 layer->texture = texture;
5534 layer->texmatrix = *matrix;
5535 layer->color[0] = r * r_refdef.view.colorscale;
5536 layer->color[1] = g * r_refdef.view.colorscale;
5537 layer->color[2] = b * r_refdef.view.colorscale;
5538 layer->color[3] = a;
5541 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5544 index = parms[2] + r_refdef.scene.time * parms[3];
5545 index -= floor(index);
5549 case Q3WAVEFUNC_NONE:
5550 case Q3WAVEFUNC_NOISE:
5551 case Q3WAVEFUNC_COUNT:
5554 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5555 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5556 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5557 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5558 case Q3WAVEFUNC_TRIANGLE:
5560 f = index - floor(index);
5571 return (float)(parms[0] + parms[1] * f);
5574 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5579 matrix4x4_t matrix, temp;
5580 switch(tcmod->tcmod)
5584 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5585 matrix = r_waterscrollmatrix;
5587 matrix = identitymatrix;
5589 case Q3TCMOD_ENTITYTRANSLATE:
5590 // this is used in Q3 to allow the gamecode to control texcoord
5591 // scrolling on the entity, which is not supported in darkplaces yet.
5592 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5594 case Q3TCMOD_ROTATE:
5595 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5596 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5597 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5600 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5602 case Q3TCMOD_SCROLL:
5603 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5605 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5606 w = (int) tcmod->parms[0];
5607 h = (int) tcmod->parms[1];
5608 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5610 idx = (int) floor(f * w * h);
5611 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5613 case Q3TCMOD_STRETCH:
5614 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5615 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5617 case Q3TCMOD_TRANSFORM:
5618 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5619 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5620 VectorSet(tcmat + 6, 0 , 0 , 1);
5621 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5622 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5624 case Q3TCMOD_TURBULENT:
5625 // this is handled in the RSurf_PrepareVertices function
5626 matrix = identitymatrix;
5630 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5633 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5635 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5636 char name[MAX_QPATH];
5637 skinframe_t *skinframe;
5638 unsigned char pixels[296*194];
5639 strlcpy(cache->name, skinname, sizeof(cache->name));
5640 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5641 if (developer_loading.integer)
5642 Con_Printf("loading %s\n", name);
5643 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5644 if (!skinframe || !skinframe->base)
5647 fs_offset_t filesize;
5649 f = FS_LoadFile(name, tempmempool, true, &filesize);
5652 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5653 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5657 cache->skinframe = skinframe;
5660 texture_t *R_GetCurrentTexture(texture_t *t)
5663 const entity_render_t *ent = rsurface.entity;
5664 dp_model_t *model = ent->model;
5665 q3shaderinfo_layer_tcmod_t *tcmod;
5667 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5668 return t->currentframe;
5669 t->update_lastrenderframe = r_frame;
5670 t->update_lastrenderentity = (void *)ent;
5672 // switch to an alternate material if this is a q1bsp animated material
5674 texture_t *texture = t;
5675 int s = rsurface.ent_skinnum;
5676 if ((unsigned int)s >= (unsigned int)model->numskins)
5678 if (model->skinscenes)
5680 if (model->skinscenes[s].framecount > 1)
5681 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5683 s = model->skinscenes[s].firstframe;
5686 t = t + s * model->num_surfaces;
5689 // use an alternate animation if the entity's frame is not 0,
5690 // and only if the texture has an alternate animation
5691 if (rsurface.ent_alttextures && t->anim_total[1])
5692 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5694 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5696 texture->currentframe = t;
5699 // update currentskinframe to be a qw skin or animation frame
5700 if (rsurface.ent_qwskin >= 0)
5702 i = rsurface.ent_qwskin;
5703 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5705 r_qwskincache_size = cl.maxclients;
5707 Mem_Free(r_qwskincache);
5708 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5710 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5711 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5712 t->currentskinframe = r_qwskincache[i].skinframe;
5713 if (t->currentskinframe == NULL)
5714 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5716 else if (t->numskinframes >= 2)
5717 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5718 if (t->backgroundnumskinframes >= 2)
5719 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5721 t->currentmaterialflags = t->basematerialflags;
5722 t->currentalpha = rsurface.ent_color[3];
5723 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5724 t->currentalpha *= r_wateralpha.value;
5725 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5726 t->currentalpha *= t->r_water_wateralpha;
5727 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5728 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5729 if (!(rsurface.ent_flags & RENDER_LIGHT))
5730 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5731 else if (rsurface.modeltexcoordlightmap2f == NULL)
5733 // pick a model lighting mode
5734 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5735 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5737 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5739 if (rsurface.ent_flags & RENDER_ADDITIVE)
5740 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5741 else if (t->currentalpha < 1)
5742 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5743 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5744 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5745 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5746 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5747 if (t->backgroundnumskinframes)
5748 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5749 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5751 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5752 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5755 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5757 // there is no tcmod
5758 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5760 t->currenttexmatrix = r_waterscrollmatrix;
5761 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5763 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5765 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5766 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5769 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5770 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5771 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5772 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5774 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5775 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5776 t->glosstexture = r_texture_black;
5777 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5778 t->backgroundglosstexture = r_texture_black;
5779 t->specularpower = r_shadow_glossexponent.value;
5780 // TODO: store reference values for these in the texture?
5781 t->specularscale = 0;
5782 if (r_shadow_gloss.integer > 0)
5784 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5786 if (r_shadow_glossintensity.value > 0)
5788 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5789 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5790 t->specularscale = r_shadow_glossintensity.value;
5793 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5795 t->glosstexture = r_texture_white;
5796 t->backgroundglosstexture = r_texture_white;
5797 t->specularscale = r_shadow_gloss2intensity.value;
5798 t->specularpower = r_shadow_gloss2exponent.value;
5801 t->specularscale *= t->specularscalemod;
5802 t->specularpower *= t->specularpowermod;
5804 // lightmaps mode looks bad with dlights using actual texturing, so turn
5805 // off the colormap and glossmap, but leave the normalmap on as it still
5806 // accurately represents the shading involved
5807 if (gl_lightmaps.integer)
5809 t->basetexture = r_texture_grey128;
5810 t->backgroundbasetexture = NULL;
5811 t->specularscale = 0;
5812 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5815 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5816 VectorClear(t->dlightcolor);
5817 t->currentnumlayers = 0;
5818 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5821 int blendfunc1, blendfunc2;
5823 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5825 blendfunc1 = GL_SRC_ALPHA;
5826 blendfunc2 = GL_ONE;
5828 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5830 blendfunc1 = GL_SRC_ALPHA;
5831 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5833 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5835 blendfunc1 = t->customblendfunc[0];
5836 blendfunc2 = t->customblendfunc[1];
5840 blendfunc1 = GL_ONE;
5841 blendfunc2 = GL_ZERO;
5843 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5844 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5845 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5846 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5848 // fullbright is not affected by r_refdef.lightmapintensity
5849 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]);
5850 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5851 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]);
5852 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5853 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]);
5857 vec3_t ambientcolor;
5859 // set the color tint used for lights affecting this surface
5860 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5862 // q3bsp has no lightmap updates, so the lightstylevalue that
5863 // would normally be baked into the lightmap must be
5864 // applied to the color
5865 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5866 if (model->type == mod_brushq3)
5867 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5868 colorscale *= r_refdef.lightmapintensity;
5869 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5870 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5871 // basic lit geometry
5872 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]);
5873 // add pants/shirt if needed
5874 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5875 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]);
5876 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5877 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]);
5878 // now add ambient passes if needed
5879 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5881 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]);
5882 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5883 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]);
5884 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5885 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]);
5888 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5889 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]);
5890 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5892 // if this is opaque use alpha blend which will darken the earlier
5895 // if this is an alpha blended material, all the earlier passes
5896 // were darkened by fog already, so we only need to add the fog
5897 // color ontop through the fog mask texture
5899 // if this is an additive blended material, all the earlier passes
5900 // were darkened by fog already, and we should not add fog color
5901 // (because the background was not darkened, there is no fog color
5902 // that was lost behind it).
5903 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]);
5907 return t->currentframe;
5910 rsurfacestate_t rsurface;
5912 void R_Mesh_ResizeArrays(int newvertices)
5915 if (rsurface.array_size >= newvertices)
5917 if (rsurface.array_modelvertex3f)
5918 Mem_Free(rsurface.array_modelvertex3f);
5919 rsurface.array_size = (newvertices + 1023) & ~1023;
5920 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5921 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5922 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5923 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5924 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5925 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5926 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5927 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5928 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5929 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5930 rsurface.array_color4f = base + rsurface.array_size * 27;
5931 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5934 void RSurf_ActiveWorldEntity(void)
5936 dp_model_t *model = r_refdef.scene.worldmodel;
5937 //if (rsurface.entity == r_refdef.scene.worldentity)
5939 rsurface.entity = r_refdef.scene.worldentity;
5940 rsurface.ent_skinnum = 0;
5941 rsurface.ent_qwskin = -1;
5942 rsurface.ent_shadertime = 0;
5943 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
5944 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
5945 if (rsurface.array_size < model->surfmesh.num_vertices)
5946 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5947 rsurface.matrix = identitymatrix;
5948 rsurface.inversematrix = identitymatrix;
5949 rsurface.matrixscale = 1;
5950 rsurface.inversematrixscale = 1;
5951 R_Mesh_Matrix(&identitymatrix);
5952 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5953 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
5954 rsurface.fograngerecip = r_refdef.fograngerecip;
5955 rsurface.fogheightfade = r_refdef.fogheightfade;
5956 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
5957 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
5958 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5959 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5960 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5961 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5962 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5963 VectorSet(rsurface.glowmod, 1, 1, 1);
5964 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5965 rsurface.frameblend[0].lerp = 1;
5966 rsurface.ent_alttextures = false;
5967 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5968 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5969 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5970 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5971 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5972 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5973 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5974 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5975 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5976 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5977 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5978 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5979 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5980 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5981 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5982 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5983 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5984 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5985 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5986 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5987 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5988 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5989 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5990 rsurface.modelelement3i = model->surfmesh.data_element3i;
5991 rsurface.modelelement3s = model->surfmesh.data_element3s;
5992 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5993 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5994 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5995 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5996 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5997 rsurface.modelsurfaces = model->data_surfaces;
5998 rsurface.generatedvertex = false;
5999 rsurface.vertex3f = rsurface.modelvertex3f;
6000 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6001 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6002 rsurface.svector3f = rsurface.modelsvector3f;
6003 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6004 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6005 rsurface.tvector3f = rsurface.modeltvector3f;
6006 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6007 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6008 rsurface.normal3f = rsurface.modelnormal3f;
6009 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6010 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6011 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6014 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6016 dp_model_t *model = ent->model;
6017 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6019 rsurface.entity = (entity_render_t *)ent;
6020 rsurface.ent_skinnum = ent->skinnum;
6021 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;
6022 rsurface.ent_shadertime = ent->shadertime;
6023 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6024 rsurface.ent_flags = ent->flags;
6025 if (rsurface.array_size < model->surfmesh.num_vertices)
6026 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6027 rsurface.matrix = ent->matrix;
6028 rsurface.inversematrix = ent->inversematrix;
6029 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6030 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6031 R_Mesh_Matrix(&rsurface.matrix);
6032 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6033 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6034 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6035 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6036 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6037 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6038 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6039 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6040 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6041 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6042 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6043 VectorCopy(ent->glowmod, rsurface.glowmod);
6044 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6045 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6046 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6047 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6048 if (ent->model->brush.submodel)
6050 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6051 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6053 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6055 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6057 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6058 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6059 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6060 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6062 else if (wanttangents)
6064 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6065 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6066 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6067 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6068 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6070 else if (wantnormals)
6072 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6073 rsurface.modelsvector3f = NULL;
6074 rsurface.modeltvector3f = NULL;
6075 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6076 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6080 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6081 rsurface.modelsvector3f = NULL;
6082 rsurface.modeltvector3f = NULL;
6083 rsurface.modelnormal3f = NULL;
6084 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6086 rsurface.modelvertex3f_bufferobject = 0;
6087 rsurface.modelvertex3f_bufferoffset = 0;
6088 rsurface.modelsvector3f_bufferobject = 0;
6089 rsurface.modelsvector3f_bufferoffset = 0;
6090 rsurface.modeltvector3f_bufferobject = 0;
6091 rsurface.modeltvector3f_bufferoffset = 0;
6092 rsurface.modelnormal3f_bufferobject = 0;
6093 rsurface.modelnormal3f_bufferoffset = 0;
6094 rsurface.generatedvertex = true;
6098 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6099 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6100 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6101 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6102 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6103 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6104 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6105 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6106 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6107 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6108 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6109 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6110 rsurface.generatedvertex = false;
6112 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6113 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6114 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6115 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6116 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6117 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6118 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6119 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6120 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6121 rsurface.modelelement3i = model->surfmesh.data_element3i;
6122 rsurface.modelelement3s = model->surfmesh.data_element3s;
6123 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6124 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6125 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6126 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6127 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6128 rsurface.modelsurfaces = model->data_surfaces;
6129 rsurface.vertex3f = rsurface.modelvertex3f;
6130 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6131 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6132 rsurface.svector3f = rsurface.modelsvector3f;
6133 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6134 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6135 rsurface.tvector3f = rsurface.modeltvector3f;
6136 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6137 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6138 rsurface.normal3f = rsurface.modelnormal3f;
6139 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6140 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6141 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6144 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
6146 rsurface.entity = r_refdef.scene.worldentity;
6147 rsurface.ent_skinnum = 0;
6148 rsurface.ent_qwskin = -1;
6149 rsurface.ent_shadertime = shadertime;
6150 Vector4Set(rsurface.ent_color, r, g, b, a);
6151 rsurface.ent_flags = entflags;
6152 rsurface.modelnum_vertices = numvertices;
6153 rsurface.modelnum_triangles = numtriangles;
6154 if (rsurface.array_size < rsurface.modelnum_vertices)
6155 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6156 rsurface.matrix = *matrix;
6157 rsurface.inversematrix = *inversematrix;
6158 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6159 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6160 R_Mesh_Matrix(&rsurface.matrix);
6161 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6162 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6163 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6164 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6165 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6166 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6167 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6168 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6169 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6170 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6171 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6172 VectorSet(rsurface.glowmod, 1, 1, 1);
6173 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6174 rsurface.frameblend[0].lerp = 1;
6175 rsurface.ent_alttextures = false;
6176 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6177 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6180 rsurface.modelvertex3f = vertex3f;
6181 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6182 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6183 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6185 else if (wantnormals)
6187 rsurface.modelvertex3f = vertex3f;
6188 rsurface.modelsvector3f = NULL;
6189 rsurface.modeltvector3f = NULL;
6190 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6194 rsurface.modelvertex3f = vertex3f;
6195 rsurface.modelsvector3f = NULL;
6196 rsurface.modeltvector3f = NULL;
6197 rsurface.modelnormal3f = NULL;
6199 rsurface.modelvertex3f_bufferobject = 0;
6200 rsurface.modelvertex3f_bufferoffset = 0;
6201 rsurface.modelsvector3f_bufferobject = 0;
6202 rsurface.modelsvector3f_bufferoffset = 0;
6203 rsurface.modeltvector3f_bufferobject = 0;
6204 rsurface.modeltvector3f_bufferoffset = 0;
6205 rsurface.modelnormal3f_bufferobject = 0;
6206 rsurface.modelnormal3f_bufferoffset = 0;
6207 rsurface.generatedvertex = true;
6208 rsurface.modellightmapcolor4f = color4f;
6209 rsurface.modellightmapcolor4f_bufferobject = 0;
6210 rsurface.modellightmapcolor4f_bufferoffset = 0;
6211 rsurface.modeltexcoordtexture2f = texcoord2f;
6212 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6213 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6214 rsurface.modeltexcoordlightmap2f = NULL;
6215 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6216 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6217 rsurface.modelelement3i = element3i;
6218 rsurface.modelelement3s = element3s;
6219 rsurface.modelelement3i_bufferobject = 0;
6220 rsurface.modelelement3s_bufferobject = 0;
6221 rsurface.modellightmapoffsets = NULL;
6222 rsurface.modelsurfaces = NULL;
6223 rsurface.vertex3f = rsurface.modelvertex3f;
6224 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6225 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6226 rsurface.svector3f = rsurface.modelsvector3f;
6227 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6228 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6229 rsurface.tvector3f = rsurface.modeltvector3f;
6230 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6231 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6232 rsurface.normal3f = rsurface.modelnormal3f;
6233 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6234 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6235 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6237 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6239 if ((wantnormals || wanttangents) && !normal3f)
6240 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6241 if (wanttangents && !svector3f)
6242 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);
6246 float RSurf_FogPoint(const float *v)
6248 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6249 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6250 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6251 float FogHeightFade = r_refdef.fogheightfade;
6253 unsigned int fogmasktableindex;
6254 if (r_refdef.fogplaneviewabove)
6255 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6257 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6258 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6259 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6262 float RSurf_FogVertex(const float *v)
6264 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6265 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6266 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6267 float FogHeightFade = rsurface.fogheightfade;
6269 unsigned int fogmasktableindex;
6270 if (r_refdef.fogplaneviewabove)
6271 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6273 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6274 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6275 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6278 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6279 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6282 int texturesurfaceindex;
6287 const float *v1, *in_tc;
6289 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6291 q3shaderinfo_deform_t *deform;
6292 // 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
6293 if (rsurface.generatedvertex)
6295 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6296 generatenormals = true;
6297 for (i = 0;i < Q3MAXDEFORMS;i++)
6299 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6301 generatetangents = true;
6302 generatenormals = true;
6304 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6305 generatenormals = true;
6307 if (generatenormals && !rsurface.modelnormal3f)
6309 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6310 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6311 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6312 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6314 if (generatetangents && !rsurface.modelsvector3f)
6316 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6317 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6318 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6319 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6320 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6321 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6322 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);
6325 rsurface.vertex3f = rsurface.modelvertex3f;
6326 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6327 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6328 rsurface.svector3f = rsurface.modelsvector3f;
6329 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6330 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6331 rsurface.tvector3f = rsurface.modeltvector3f;
6332 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6333 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6334 rsurface.normal3f = rsurface.modelnormal3f;
6335 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6336 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6337 // if vertices are deformed (sprite flares and things in maps, possibly
6338 // water waves, bulges and other deformations), generate them into
6339 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6340 // (may be static model data or generated data for an animated model, or
6341 // the previous deform pass)
6342 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6344 switch (deform->deform)
6347 case Q3DEFORM_PROJECTIONSHADOW:
6348 case Q3DEFORM_TEXT0:
6349 case Q3DEFORM_TEXT1:
6350 case Q3DEFORM_TEXT2:
6351 case Q3DEFORM_TEXT3:
6352 case Q3DEFORM_TEXT4:
6353 case Q3DEFORM_TEXT5:
6354 case Q3DEFORM_TEXT6:
6355 case Q3DEFORM_TEXT7:
6358 case Q3DEFORM_AUTOSPRITE:
6359 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6360 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6361 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6362 VectorNormalize(newforward);
6363 VectorNormalize(newright);
6364 VectorNormalize(newup);
6365 // make deformed versions of only the model vertices used by the specified surfaces
6366 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6368 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6369 // a single autosprite surface can contain multiple sprites...
6370 for (j = 0;j < surface->num_vertices - 3;j += 4)
6372 VectorClear(center);
6373 for (i = 0;i < 4;i++)
6374 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6375 VectorScale(center, 0.25f, center);
6376 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6377 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6378 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6379 for (i = 0;i < 4;i++)
6381 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6382 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6385 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);
6386 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);
6388 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6389 rsurface.vertex3f_bufferobject = 0;
6390 rsurface.vertex3f_bufferoffset = 0;
6391 rsurface.svector3f = rsurface.array_deformedsvector3f;
6392 rsurface.svector3f_bufferobject = 0;
6393 rsurface.svector3f_bufferoffset = 0;
6394 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6395 rsurface.tvector3f_bufferobject = 0;
6396 rsurface.tvector3f_bufferoffset = 0;
6397 rsurface.normal3f = rsurface.array_deformednormal3f;
6398 rsurface.normal3f_bufferobject = 0;
6399 rsurface.normal3f_bufferoffset = 0;
6401 case Q3DEFORM_AUTOSPRITE2:
6402 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6403 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6404 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6405 VectorNormalize(newforward);
6406 VectorNormalize(newright);
6407 VectorNormalize(newup);
6408 // make deformed versions of only the model vertices used by the specified surfaces
6409 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6411 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6412 const float *v1, *v2;
6422 memset(shortest, 0, sizeof(shortest));
6423 // a single autosprite surface can contain multiple sprites...
6424 for (j = 0;j < surface->num_vertices - 3;j += 4)
6426 VectorClear(center);
6427 for (i = 0;i < 4;i++)
6428 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6429 VectorScale(center, 0.25f, center);
6430 // find the two shortest edges, then use them to define the
6431 // axis vectors for rotating around the central axis
6432 for (i = 0;i < 6;i++)
6434 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6435 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6437 Debug_PolygonBegin(NULL, 0);
6438 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6439 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);
6440 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6443 l = VectorDistance2(v1, v2);
6444 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6446 l += (1.0f / 1024.0f);
6447 if (shortest[0].length2 > l || i == 0)
6449 shortest[1] = shortest[0];
6450 shortest[0].length2 = l;
6451 shortest[0].v1 = v1;
6452 shortest[0].v2 = v2;
6454 else if (shortest[1].length2 > l || i == 1)
6456 shortest[1].length2 = l;
6457 shortest[1].v1 = v1;
6458 shortest[1].v2 = v2;
6461 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6462 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6464 Debug_PolygonBegin(NULL, 0);
6465 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6466 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);
6467 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6470 // this calculates the right vector from the shortest edge
6471 // and the up vector from the edge midpoints
6472 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6473 VectorNormalize(right);
6474 VectorSubtract(end, start, up);
6475 VectorNormalize(up);
6476 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6477 VectorSubtract(rsurface.localvieworigin, center, forward);
6478 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6479 VectorNegate(forward, forward);
6480 VectorReflect(forward, 0, up, forward);
6481 VectorNormalize(forward);
6482 CrossProduct(up, forward, newright);
6483 VectorNormalize(newright);
6485 Debug_PolygonBegin(NULL, 0);
6486 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);
6487 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6488 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6492 Debug_PolygonBegin(NULL, 0);
6493 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6494 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6495 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6498 // rotate the quad around the up axis vector, this is made
6499 // especially easy by the fact we know the quad is flat,
6500 // so we only have to subtract the center position and
6501 // measure distance along the right vector, and then
6502 // multiply that by the newright vector and add back the
6504 // we also need to subtract the old position to undo the
6505 // displacement from the center, which we do with a
6506 // DotProduct, the subtraction/addition of center is also
6507 // optimized into DotProducts here
6508 l = DotProduct(right, center);
6509 for (i = 0;i < 4;i++)
6511 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6512 f = DotProduct(right, v1) - l;
6513 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6516 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);
6517 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);
6519 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6520 rsurface.vertex3f_bufferobject = 0;
6521 rsurface.vertex3f_bufferoffset = 0;
6522 rsurface.svector3f = rsurface.array_deformedsvector3f;
6523 rsurface.svector3f_bufferobject = 0;
6524 rsurface.svector3f_bufferoffset = 0;
6525 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6526 rsurface.tvector3f_bufferobject = 0;
6527 rsurface.tvector3f_bufferoffset = 0;
6528 rsurface.normal3f = rsurface.array_deformednormal3f;
6529 rsurface.normal3f_bufferobject = 0;
6530 rsurface.normal3f_bufferoffset = 0;
6532 case Q3DEFORM_NORMAL:
6533 // deform the normals to make reflections wavey
6534 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6536 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6537 for (j = 0;j < surface->num_vertices;j++)
6540 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6541 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6542 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6543 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6544 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6545 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6546 VectorNormalize(normal);
6548 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);
6550 rsurface.svector3f = rsurface.array_deformedsvector3f;
6551 rsurface.svector3f_bufferobject = 0;
6552 rsurface.svector3f_bufferoffset = 0;
6553 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6554 rsurface.tvector3f_bufferobject = 0;
6555 rsurface.tvector3f_bufferoffset = 0;
6556 rsurface.normal3f = rsurface.array_deformednormal3f;
6557 rsurface.normal3f_bufferobject = 0;
6558 rsurface.normal3f_bufferoffset = 0;
6561 // deform vertex array to make wavey water and flags and such
6562 waveparms[0] = deform->waveparms[0];
6563 waveparms[1] = deform->waveparms[1];
6564 waveparms[2] = deform->waveparms[2];
6565 waveparms[3] = deform->waveparms[3];
6566 // this is how a divisor of vertex influence on deformation
6567 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6568 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6569 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6571 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6572 for (j = 0;j < surface->num_vertices;j++)
6574 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6575 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6576 // if the wavefunc depends on time, evaluate it per-vertex
6579 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6580 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6582 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6585 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6586 rsurface.vertex3f_bufferobject = 0;
6587 rsurface.vertex3f_bufferoffset = 0;
6589 case Q3DEFORM_BULGE:
6590 // deform vertex array to make the surface have moving bulges
6591 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6593 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6594 for (j = 0;j < surface->num_vertices;j++)
6596 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6597 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6600 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6601 rsurface.vertex3f_bufferobject = 0;
6602 rsurface.vertex3f_bufferoffset = 0;
6605 // deform vertex array
6606 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6607 VectorScale(deform->parms, scale, waveparms);
6608 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6610 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6611 for (j = 0;j < surface->num_vertices;j++)
6612 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6614 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6615 rsurface.vertex3f_bufferobject = 0;
6616 rsurface.vertex3f_bufferoffset = 0;
6620 // generate texcoords based on the chosen texcoord source
6621 switch(rsurface.texture->tcgen.tcgen)
6624 case Q3TCGEN_TEXTURE:
6625 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6626 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6627 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6629 case Q3TCGEN_LIGHTMAP:
6630 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6631 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6632 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6634 case Q3TCGEN_VECTOR:
6635 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6637 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6638 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)
6640 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6641 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6644 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6645 rsurface.texcoordtexture2f_bufferobject = 0;
6646 rsurface.texcoordtexture2f_bufferoffset = 0;
6648 case Q3TCGEN_ENVIRONMENT:
6649 // make environment reflections using a spheremap
6650 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6652 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6653 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6654 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6655 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6656 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6658 // identical to Q3A's method, but executed in worldspace so
6659 // carried models can be shiny too
6661 float viewer[3], d, reflected[3], worldreflected[3];
6663 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6664 // VectorNormalize(viewer);
6666 d = DotProduct(normal, viewer);
6668 reflected[0] = normal[0]*2*d - viewer[0];
6669 reflected[1] = normal[1]*2*d - viewer[1];
6670 reflected[2] = normal[2]*2*d - viewer[2];
6671 // note: this is proportinal to viewer, so we can normalize later
6673 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6674 VectorNormalize(worldreflected);
6676 // note: this sphere map only uses world x and z!
6677 // so positive and negative y will LOOK THE SAME.
6678 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6679 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6682 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6683 rsurface.texcoordtexture2f_bufferobject = 0;
6684 rsurface.texcoordtexture2f_bufferoffset = 0;
6687 // the only tcmod that needs software vertex processing is turbulent, so
6688 // check for it here and apply the changes if needed
6689 // and we only support that as the first one
6690 // (handling a mixture of turbulent and other tcmods would be problematic
6691 // without punting it entirely to a software path)
6692 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6694 amplitude = rsurface.texture->tcmods[0].parms[1];
6695 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6696 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6698 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6699 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)
6701 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6702 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6705 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6706 rsurface.texcoordtexture2f_bufferobject = 0;
6707 rsurface.texcoordtexture2f_bufferoffset = 0;
6709 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6710 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6711 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6712 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6715 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6718 const msurface_t *surface = texturesurfacelist[0];
6719 const msurface_t *surface2;
6724 // TODO: lock all array ranges before render, rather than on each surface
6725 if (texturenumsurfaces == 1)
6727 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6728 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);
6730 else if (r_batchmode.integer == 2)
6732 #define MAXBATCHTRIANGLES 4096
6733 int batchtriangles = 0;
6734 int batchelements[MAXBATCHTRIANGLES*3];
6735 for (i = 0;i < texturenumsurfaces;i = j)
6737 surface = texturesurfacelist[i];
6739 if (surface->num_triangles > MAXBATCHTRIANGLES)
6741 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);
6744 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6745 batchtriangles = surface->num_triangles;
6746 firstvertex = surface->num_firstvertex;
6747 endvertex = surface->num_firstvertex + surface->num_vertices;
6748 for (;j < texturenumsurfaces;j++)
6750 surface2 = texturesurfacelist[j];
6751 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6753 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6754 batchtriangles += surface2->num_triangles;
6755 firstvertex = min(firstvertex, surface2->num_firstvertex);
6756 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6758 surface2 = texturesurfacelist[j-1];
6759 numvertices = endvertex - firstvertex;
6760 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6763 else if (r_batchmode.integer == 1)
6765 for (i = 0;i < texturenumsurfaces;i = j)
6767 surface = texturesurfacelist[i];
6768 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6769 if (texturesurfacelist[j] != surface2)
6771 surface2 = texturesurfacelist[j-1];
6772 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6773 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6774 GL_LockArrays(surface->num_firstvertex, numvertices);
6775 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6780 for (i = 0;i < texturenumsurfaces;i++)
6782 surface = texturesurfacelist[i];
6783 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6784 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);
6789 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6791 int i, planeindex, vertexindex;
6795 r_waterstate_waterplane_t *p, *bestp;
6796 const msurface_t *surface;
6797 if (r_waterstate.renderingscene)
6799 for (i = 0;i < texturenumsurfaces;i++)
6801 surface = texturesurfacelist[i];
6802 if (lightmaptexunit >= 0)
6803 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6804 if (deluxemaptexunit >= 0)
6805 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6806 // pick the closest matching water plane
6809 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6812 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6814 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6815 d += fabs(PlaneDiff(vert, &p->plane));
6817 if (bestd > d || !bestp)
6825 if (refractiontexunit >= 0)
6826 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6827 if (reflectiontexunit >= 0)
6828 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6832 if (refractiontexunit >= 0)
6833 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6834 if (reflectiontexunit >= 0)
6835 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6837 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6838 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);
6842 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6846 const msurface_t *surface = texturesurfacelist[0];
6847 const msurface_t *surface2;
6852 // TODO: lock all array ranges before render, rather than on each surface
6853 if (texturenumsurfaces == 1)
6855 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6856 if (deluxemaptexunit >= 0)
6857 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6858 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6859 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);
6861 else if (r_batchmode.integer == 2)
6863 #define MAXBATCHTRIANGLES 4096
6864 int batchtriangles = 0;
6865 int batchelements[MAXBATCHTRIANGLES*3];
6866 for (i = 0;i < texturenumsurfaces;i = j)
6868 surface = texturesurfacelist[i];
6869 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6870 if (deluxemaptexunit >= 0)
6871 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6873 if (surface->num_triangles > MAXBATCHTRIANGLES)
6875 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);
6878 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6879 batchtriangles = surface->num_triangles;
6880 firstvertex = surface->num_firstvertex;
6881 endvertex = surface->num_firstvertex + surface->num_vertices;
6882 for (;j < texturenumsurfaces;j++)
6884 surface2 = texturesurfacelist[j];
6885 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6887 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6888 batchtriangles += surface2->num_triangles;
6889 firstvertex = min(firstvertex, surface2->num_firstvertex);
6890 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6892 surface2 = texturesurfacelist[j-1];
6893 numvertices = endvertex - firstvertex;
6894 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6897 else if (r_batchmode.integer == 1)
6900 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6901 for (i = 0;i < texturenumsurfaces;i = j)
6903 surface = texturesurfacelist[i];
6904 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6905 if (texturesurfacelist[j] != surface2)
6907 Con_Printf(" %i", j - i);
6910 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6912 for (i = 0;i < texturenumsurfaces;i = j)
6914 surface = texturesurfacelist[i];
6915 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6916 if (deluxemaptexunit >= 0)
6917 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6918 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6919 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6922 Con_Printf(" %i", j - i);
6924 surface2 = texturesurfacelist[j-1];
6925 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6926 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6927 GL_LockArrays(surface->num_firstvertex, numvertices);
6928 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6936 for (i = 0;i < texturenumsurfaces;i++)
6938 surface = texturesurfacelist[i];
6939 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6940 if (deluxemaptexunit >= 0)
6941 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6942 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6943 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);
6948 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6951 int texturesurfaceindex;
6952 if (r_showsurfaces.integer == 2)
6954 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6956 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6957 for (j = 0;j < surface->num_triangles;j++)
6959 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6960 GL_Color(f, f, f, 1);
6961 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6967 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6969 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6970 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6971 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);
6972 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6973 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);
6978 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6980 int texturesurfaceindex;
6984 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6986 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6987 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)
6995 rsurface.lightmapcolor4f = rsurface.array_color4f;
6996 rsurface.lightmapcolor4f_bufferobject = 0;
6997 rsurface.lightmapcolor4f_bufferoffset = 0;
7000 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7002 int texturesurfaceindex;
7008 if (rsurface.lightmapcolor4f)
7010 // generate color arrays for the surfaces in this list
7011 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7013 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7014 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)
7016 f = RSurf_FogVertex(v);
7026 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7028 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7029 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)
7031 f = RSurf_FogVertex(v);
7039 rsurface.lightmapcolor4f = rsurface.array_color4f;
7040 rsurface.lightmapcolor4f_bufferobject = 0;
7041 rsurface.lightmapcolor4f_bufferoffset = 0;
7044 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7046 int texturesurfaceindex;
7052 if (!rsurface.lightmapcolor4f)
7054 // generate color arrays for the surfaces in this list
7055 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7057 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7058 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)
7060 f = RSurf_FogVertex(v);
7061 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7062 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7063 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7067 rsurface.lightmapcolor4f = rsurface.array_color4f;
7068 rsurface.lightmapcolor4f_bufferobject = 0;
7069 rsurface.lightmapcolor4f_bufferoffset = 0;
7072 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7074 int texturesurfaceindex;
7078 if (!rsurface.lightmapcolor4f)
7080 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7082 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7083 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)
7091 rsurface.lightmapcolor4f = rsurface.array_color4f;
7092 rsurface.lightmapcolor4f_bufferobject = 0;
7093 rsurface.lightmapcolor4f_bufferoffset = 0;
7096 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7098 int texturesurfaceindex;
7102 if (!rsurface.lightmapcolor4f)
7104 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7106 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7107 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)
7109 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7110 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7111 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7115 rsurface.lightmapcolor4f = rsurface.array_color4f;
7116 rsurface.lightmapcolor4f_bufferobject = 0;
7117 rsurface.lightmapcolor4f_bufferoffset = 0;
7120 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7123 rsurface.lightmapcolor4f = NULL;
7124 rsurface.lightmapcolor4f_bufferobject = 0;
7125 rsurface.lightmapcolor4f_bufferoffset = 0;
7126 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7127 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7128 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7129 GL_Color(r, g, b, a);
7130 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7133 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7135 // TODO: optimize applyfog && applycolor case
7136 // just apply fog if necessary, and tint the fog color array if necessary
7137 rsurface.lightmapcolor4f = NULL;
7138 rsurface.lightmapcolor4f_bufferobject = 0;
7139 rsurface.lightmapcolor4f_bufferoffset = 0;
7140 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7141 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7142 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7143 GL_Color(r, g, b, a);
7144 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7147 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7149 int texturesurfaceindex;
7153 if (texturesurfacelist[0]->lightmapinfo)
7155 // generate color arrays for the surfaces in this list
7156 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7158 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7159 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7161 if (surface->lightmapinfo->samples)
7163 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7164 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7165 VectorScale(lm, scale, c);
7166 if (surface->lightmapinfo->styles[1] != 255)
7168 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7170 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7171 VectorMA(c, scale, lm, c);
7172 if (surface->lightmapinfo->styles[2] != 255)
7175 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7176 VectorMA(c, scale, lm, c);
7177 if (surface->lightmapinfo->styles[3] != 255)
7180 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7181 VectorMA(c, scale, lm, c);
7191 rsurface.lightmapcolor4f = rsurface.array_color4f;
7192 rsurface.lightmapcolor4f_bufferobject = 0;
7193 rsurface.lightmapcolor4f_bufferoffset = 0;
7197 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7198 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7199 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7201 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7202 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7203 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7204 GL_Color(r, g, b, a);
7205 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7208 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7210 int texturesurfaceindex;
7217 vec3_t ambientcolor;
7218 vec3_t diffusecolor;
7222 VectorCopy(rsurface.modellight_lightdir, lightdir);
7223 f = 0.5f * r_refdef.lightmapintensity;
7224 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7225 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7226 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7227 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7228 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7229 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7231 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7233 // generate color arrays for the surfaces in this list
7234 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7236 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7237 int numverts = surface->num_vertices;
7238 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7239 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7240 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7241 // q3-style directional shading
7242 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7244 if ((f = DotProduct(n, lightdir)) > 0)
7245 VectorMA(ambientcolor, f, diffusecolor, c);
7247 VectorCopy(ambientcolor, c);
7255 rsurface.lightmapcolor4f = rsurface.array_color4f;
7256 rsurface.lightmapcolor4f_bufferobject = 0;
7257 rsurface.lightmapcolor4f_bufferoffset = 0;
7258 *applycolor = false;
7262 *r = ambientcolor[0];
7263 *g = ambientcolor[1];
7264 *b = ambientcolor[2];
7265 rsurface.lightmapcolor4f = NULL;
7266 rsurface.lightmapcolor4f_bufferobject = 0;
7267 rsurface.lightmapcolor4f_bufferoffset = 0;
7271 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7273 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7274 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7275 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7276 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7277 GL_Color(r, g, b, a);
7278 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7281 void RSurf_SetupDepthAndCulling(void)
7283 // submodels are biased to avoid z-fighting with world surfaces that they
7284 // may be exactly overlapping (avoids z-fighting artifacts on certain
7285 // doors and things in Quake maps)
7286 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7287 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7288 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7289 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7292 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7294 // transparent sky would be ridiculous
7295 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7297 R_SetupGenericShader(false);
7298 skyrenderlater = true;
7299 RSurf_SetupDepthAndCulling();
7301 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7302 // skymasking on them, and Quake3 never did sky masking (unlike
7303 // software Quake and software Quake2), so disable the sky masking
7304 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7305 // and skymasking also looks very bad when noclipping outside the
7306 // level, so don't use it then either.
7307 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7309 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7310 R_Mesh_ColorPointer(NULL, 0, 0);
7311 R_Mesh_ResetTextureState();
7312 if (skyrendermasked)
7314 R_SetupDepthOrShadowShader();
7315 // depth-only (masking)
7316 GL_ColorMask(0,0,0,0);
7317 // just to make sure that braindead drivers don't draw
7318 // anything despite that colormask...
7319 GL_BlendFunc(GL_ZERO, GL_ONE);
7323 R_SetupGenericShader(false);
7325 GL_BlendFunc(GL_ONE, GL_ZERO);
7327 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7328 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7329 if (skyrendermasked)
7330 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7332 R_Mesh_ResetTextureState();
7333 GL_Color(1, 1, 1, 1);
7336 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7338 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7341 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7342 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7343 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7344 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7345 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7346 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7347 if (rsurface.texture->backgroundcurrentskinframe)
7349 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7350 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7351 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7352 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7354 if(rsurface.texture->colormapping)
7356 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7357 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7359 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7360 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7361 R_Mesh_ColorPointer(NULL, 0, 0);
7363 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7365 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7367 // render background
7368 GL_BlendFunc(GL_ONE, GL_ZERO);
7370 GL_AlphaTest(false);
7372 GL_Color(1, 1, 1, 1);
7373 R_Mesh_ColorPointer(NULL, 0, 0);
7375 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7376 if (r_glsl_permutation)
7378 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7379 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7380 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7381 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7382 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7383 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7384 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);
7386 GL_LockArrays(0, 0);
7388 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7389 GL_DepthMask(false);
7390 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7391 R_Mesh_ColorPointer(NULL, 0, 0);
7393 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7394 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7395 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7398 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7399 if (!r_glsl_permutation)
7402 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7403 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7404 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7405 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7406 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7407 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7409 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7411 GL_BlendFunc(GL_ONE, GL_ZERO);
7413 GL_AlphaTest(false);
7417 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7418 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7419 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7422 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7424 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7425 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);
7427 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7431 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7432 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);
7434 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7436 GL_LockArrays(0, 0);
7439 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7441 // OpenGL 1.3 path - anything not completely ancient
7442 int texturesurfaceindex;
7443 qboolean applycolor;
7447 const texturelayer_t *layer;
7448 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7450 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7453 int layertexrgbscale;
7454 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7456 if (layerindex == 0)
7460 GL_AlphaTest(false);
7461 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7464 GL_DepthMask(layer->depthmask && writedepth);
7465 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7466 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7468 layertexrgbscale = 4;
7469 VectorScale(layer->color, 0.25f, layercolor);
7471 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7473 layertexrgbscale = 2;
7474 VectorScale(layer->color, 0.5f, layercolor);
7478 layertexrgbscale = 1;
7479 VectorScale(layer->color, 1.0f, layercolor);
7481 layercolor[3] = layer->color[3];
7482 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7483 R_Mesh_ColorPointer(NULL, 0, 0);
7484 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7485 switch (layer->type)
7487 case TEXTURELAYERTYPE_LITTEXTURE:
7488 memset(&m, 0, sizeof(m));
7489 m.tex[0] = R_GetTexture(r_texture_white);
7490 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7491 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7492 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7493 m.tex[1] = R_GetTexture(layer->texture);
7494 m.texmatrix[1] = layer->texmatrix;
7495 m.texrgbscale[1] = layertexrgbscale;
7496 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7497 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7498 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7499 R_Mesh_TextureState(&m);
7500 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7501 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7502 else if (rsurface.uselightmaptexture)
7503 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7505 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7507 case TEXTURELAYERTYPE_TEXTURE:
7508 memset(&m, 0, sizeof(m));
7509 m.tex[0] = R_GetTexture(layer->texture);
7510 m.texmatrix[0] = layer->texmatrix;
7511 m.texrgbscale[0] = layertexrgbscale;
7512 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7513 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7514 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7515 R_Mesh_TextureState(&m);
7516 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7518 case TEXTURELAYERTYPE_FOG:
7519 memset(&m, 0, sizeof(m));
7520 m.texrgbscale[0] = layertexrgbscale;
7523 m.tex[0] = R_GetTexture(layer->texture);
7524 m.texmatrix[0] = layer->texmatrix;
7525 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7526 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7527 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7529 R_Mesh_TextureState(&m);
7530 // generate a color array for the fog pass
7531 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7532 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7538 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7539 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)
7541 f = 1 - RSurf_FogVertex(v);
7542 c[0] = layercolor[0];
7543 c[1] = layercolor[1];
7544 c[2] = layercolor[2];
7545 c[3] = f * layercolor[3];
7548 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7551 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7553 GL_LockArrays(0, 0);
7556 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7558 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7559 GL_AlphaTest(false);
7563 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7565 // OpenGL 1.1 - crusty old voodoo path
7566 int texturesurfaceindex;
7570 const texturelayer_t *layer;
7571 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7573 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7575 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7577 if (layerindex == 0)
7581 GL_AlphaTest(false);
7582 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7585 GL_DepthMask(layer->depthmask && writedepth);
7586 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7587 R_Mesh_ColorPointer(NULL, 0, 0);
7588 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7589 switch (layer->type)
7591 case TEXTURELAYERTYPE_LITTEXTURE:
7592 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7594 // two-pass lit texture with 2x rgbscale
7595 // first the lightmap pass
7596 memset(&m, 0, sizeof(m));
7597 m.tex[0] = R_GetTexture(r_texture_white);
7598 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7599 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7600 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7601 R_Mesh_TextureState(&m);
7602 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7603 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7604 else if (rsurface.uselightmaptexture)
7605 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7607 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7608 GL_LockArrays(0, 0);
7609 // then apply the texture to it
7610 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7611 memset(&m, 0, sizeof(m));
7612 m.tex[0] = R_GetTexture(layer->texture);
7613 m.texmatrix[0] = layer->texmatrix;
7614 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7615 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7616 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7617 R_Mesh_TextureState(&m);
7618 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);
7622 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7623 memset(&m, 0, sizeof(m));
7624 m.tex[0] = R_GetTexture(layer->texture);
7625 m.texmatrix[0] = layer->texmatrix;
7626 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7627 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7628 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7629 R_Mesh_TextureState(&m);
7630 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7631 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);
7633 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);
7636 case TEXTURELAYERTYPE_TEXTURE:
7637 // singletexture unlit texture with transparency support
7638 memset(&m, 0, sizeof(m));
7639 m.tex[0] = R_GetTexture(layer->texture);
7640 m.texmatrix[0] = layer->texmatrix;
7641 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7642 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7643 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7644 R_Mesh_TextureState(&m);
7645 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);
7647 case TEXTURELAYERTYPE_FOG:
7648 // singletexture fogging
7649 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7652 memset(&m, 0, sizeof(m));
7653 m.tex[0] = R_GetTexture(layer->texture);
7654 m.texmatrix[0] = layer->texmatrix;
7655 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7656 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7657 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7658 R_Mesh_TextureState(&m);
7661 R_Mesh_ResetTextureState();
7662 // generate a color array for the fog pass
7663 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7669 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7670 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)
7672 f = 1 - RSurf_FogVertex(v);
7673 c[0] = layer->color[0];
7674 c[1] = layer->color[1];
7675 c[2] = layer->color[2];
7676 c[3] = f * layer->color[3];
7679 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7682 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7684 GL_LockArrays(0, 0);
7687 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7689 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7690 GL_AlphaTest(false);
7694 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7698 GL_AlphaTest(false);
7699 R_Mesh_ColorPointer(NULL, 0, 0);
7700 R_Mesh_ResetTextureState();
7701 R_SetupGenericShader(false);
7703 if(rsurface.texture && rsurface.texture->currentskinframe)
7705 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7706 c[3] *= rsurface.texture->currentalpha;
7716 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7718 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7719 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7720 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7723 // brighten it up (as texture value 127 means "unlit")
7724 c[0] *= 2 * r_refdef.view.colorscale;
7725 c[1] *= 2 * r_refdef.view.colorscale;
7726 c[2] *= 2 * r_refdef.view.colorscale;
7728 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7729 c[3] *= r_wateralpha.value;
7731 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7733 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7734 GL_DepthMask(false);
7736 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7738 GL_BlendFunc(GL_ONE, GL_ONE);
7739 GL_DepthMask(false);
7741 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7743 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7744 GL_DepthMask(false);
7746 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7748 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7749 GL_DepthMask(false);
7753 GL_BlendFunc(GL_ONE, GL_ZERO);
7754 GL_DepthMask(writedepth);
7757 rsurface.lightmapcolor4f = NULL;
7759 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7761 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7763 rsurface.lightmapcolor4f = NULL;
7764 rsurface.lightmapcolor4f_bufferobject = 0;
7765 rsurface.lightmapcolor4f_bufferoffset = 0;
7767 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7769 qboolean applycolor = true;
7772 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7774 r_refdef.lightmapintensity = 1;
7775 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7776 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7780 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7782 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7783 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7784 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7787 if(!rsurface.lightmapcolor4f)
7788 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7790 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7791 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7792 if(r_refdef.fogenabled)
7793 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7795 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7796 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7799 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7802 RSurf_SetupDepthAndCulling();
7803 if (r_showsurfaces.integer == 3)
7804 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7805 else if (r_glsl.integer && gl_support_fragment_shader)
7806 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7807 else if (gl_combine.integer && r_textureunits.integer >= 2)
7808 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7810 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7814 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7817 RSurf_SetupDepthAndCulling();
7818 if (r_showsurfaces.integer == 3)
7819 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7820 else if (r_glsl.integer && gl_support_fragment_shader)
7821 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7822 else if (gl_combine.integer && r_textureunits.integer >= 2)
7823 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7825 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7829 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7832 int texturenumsurfaces, endsurface;
7834 const msurface_t *surface;
7835 const msurface_t *texturesurfacelist[1024];
7837 // if the model is static it doesn't matter what value we give for
7838 // wantnormals and wanttangents, so this logic uses only rules applicable
7839 // to a model, knowing that they are meaningless otherwise
7840 if (ent == r_refdef.scene.worldentity)
7841 RSurf_ActiveWorldEntity();
7842 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7843 RSurf_ActiveModelEntity(ent, false, false);
7845 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7847 for (i = 0;i < numsurfaces;i = j)
7850 surface = rsurface.modelsurfaces + surfacelist[i];
7851 texture = surface->texture;
7852 rsurface.texture = R_GetCurrentTexture(texture);
7853 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7854 // scan ahead until we find a different texture
7855 endsurface = min(i + 1024, numsurfaces);
7856 texturenumsurfaces = 0;
7857 texturesurfacelist[texturenumsurfaces++] = surface;
7858 for (;j < endsurface;j++)
7860 surface = rsurface.modelsurfaces + surfacelist[j];
7861 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7863 texturesurfacelist[texturenumsurfaces++] = surface;
7865 // render the range of surfaces
7866 if (ent == r_refdef.scene.worldentity)
7867 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7869 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7871 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7872 GL_AlphaTest(false);
7875 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7877 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7881 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7883 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7885 RSurf_SetupDepthAndCulling();
7886 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7887 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7889 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7891 RSurf_SetupDepthAndCulling();
7892 GL_AlphaTest(false);
7893 R_Mesh_ColorPointer(NULL, 0, 0);
7894 R_Mesh_ResetTextureState();
7895 R_SetupGenericShader(false);
7896 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7898 GL_BlendFunc(GL_ONE, GL_ZERO);
7899 GL_Color(0, 0, 0, 1);
7900 GL_DepthTest(writedepth);
7901 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7903 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7905 RSurf_SetupDepthAndCulling();
7906 GL_AlphaTest(false);
7907 R_Mesh_ColorPointer(NULL, 0, 0);
7908 R_Mesh_ResetTextureState();
7909 R_SetupGenericShader(false);
7910 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7912 GL_BlendFunc(GL_ONE, GL_ZERO);
7914 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7916 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7917 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7918 else if (!rsurface.texture->currentnumlayers)
7920 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7922 // transparent surfaces get pushed off into the transparent queue
7923 int surfacelistindex;
7924 const msurface_t *surface;
7925 vec3_t tempcenter, center;
7926 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7928 surface = texturesurfacelist[surfacelistindex];
7929 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7930 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7931 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7932 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7933 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7938 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7939 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7944 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7948 // break the surface list down into batches by texture and use of lightmapping
7949 for (i = 0;i < numsurfaces;i = j)
7952 // texture is the base texture pointer, rsurface.texture is the
7953 // current frame/skin the texture is directing us to use (for example
7954 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7955 // use skin 1 instead)
7956 texture = surfacelist[i]->texture;
7957 rsurface.texture = R_GetCurrentTexture(texture);
7958 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7959 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7961 // if this texture is not the kind we want, skip ahead to the next one
7962 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7966 // simply scan ahead until we find a different texture or lightmap state
7967 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7969 // render the range of surfaces
7970 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7974 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7979 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7981 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7983 RSurf_SetupDepthAndCulling();
7984 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7985 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7987 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7989 RSurf_SetupDepthAndCulling();
7990 GL_AlphaTest(false);
7991 R_Mesh_ColorPointer(NULL, 0, 0);
7992 R_Mesh_ResetTextureState();
7993 R_SetupGenericShader(false);
7994 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7996 GL_BlendFunc(GL_ONE, GL_ZERO);
7997 GL_Color(0, 0, 0, 1);
7998 GL_DepthTest(writedepth);
7999 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8001 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8003 RSurf_SetupDepthAndCulling();
8004 GL_AlphaTest(false);
8005 R_Mesh_ColorPointer(NULL, 0, 0);
8006 R_Mesh_ResetTextureState();
8007 R_SetupGenericShader(false);
8008 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8010 GL_BlendFunc(GL_ONE, GL_ZERO);
8012 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8014 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8015 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8016 else if (!rsurface.texture->currentnumlayers)
8018 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8020 // transparent surfaces get pushed off into the transparent queue
8021 int surfacelistindex;
8022 const msurface_t *surface;
8023 vec3_t tempcenter, center;
8024 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8026 surface = texturesurfacelist[surfacelistindex];
8027 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8028 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8029 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8030 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8031 if (queueentity->transparent_offset) // transparent offset
8033 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8034 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8035 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8037 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8042 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8043 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8048 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8052 // break the surface list down into batches by texture and use of lightmapping
8053 for (i = 0;i < numsurfaces;i = j)
8056 // texture is the base texture pointer, rsurface.texture is the
8057 // current frame/skin the texture is directing us to use (for example
8058 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8059 // use skin 1 instead)
8060 texture = surfacelist[i]->texture;
8061 rsurface.texture = R_GetCurrentTexture(texture);
8062 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8063 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8065 // if this texture is not the kind we want, skip ahead to the next one
8066 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8070 // simply scan ahead until we find a different texture or lightmap state
8071 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8073 // render the range of surfaces
8074 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8078 float locboxvertex3f[6*4*3] =
8080 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8081 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8082 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8083 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8084 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8085 1,0,0, 0,0,0, 0,1,0, 1,1,0
8088 unsigned short locboxelements[6*2*3] =
8098 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8101 cl_locnode_t *loc = (cl_locnode_t *)ent;
8103 float vertex3f[6*4*3];
8105 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8106 GL_DepthMask(false);
8107 GL_DepthRange(0, 1);
8108 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8110 GL_CullFace(GL_NONE);
8111 R_Mesh_Matrix(&identitymatrix);
8113 R_Mesh_VertexPointer(vertex3f, 0, 0);
8114 R_Mesh_ColorPointer(NULL, 0, 0);
8115 R_Mesh_ResetTextureState();
8116 R_SetupGenericShader(false);
8119 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8120 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8121 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8122 surfacelist[0] < 0 ? 0.5f : 0.125f);
8124 if (VectorCompare(loc->mins, loc->maxs))
8126 VectorSet(size, 2, 2, 2);
8127 VectorMA(loc->mins, -0.5f, size, mins);
8131 VectorCopy(loc->mins, mins);
8132 VectorSubtract(loc->maxs, loc->mins, size);
8135 for (i = 0;i < 6*4*3;)
8136 for (j = 0;j < 3;j++, i++)
8137 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8139 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8142 void R_DrawLocs(void)
8145 cl_locnode_t *loc, *nearestloc;
8147 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8148 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8150 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8151 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8155 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8157 if (decalsystem->decals)
8158 Mem_Free(decalsystem->decals);
8159 memset(decalsystem, 0, sizeof(*decalsystem));
8162 void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex)
8173 // expand or initialize the system
8174 if (decalsystem->maxdecals <= decalsystem->numdecals)
8176 decalsystem_t old = *decalsystem;
8177 qboolean useshortelements;
8178 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8179 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8180 decalsystem->decals = Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
8181 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8182 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8183 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8184 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8185 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8186 if (decalsystem->numdecals)
8188 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8189 memcpy(decalsystem->vertex3f, old.vertex3f, decalsystem->numdecals * sizeof(float[3][3]));
8190 memcpy(decalsystem->texcoord2f, old.texcoord2f, decalsystem->numdecals * sizeof(float[3][2]));
8191 memcpy(decalsystem->color4f, old.color4f, decalsystem->numdecals * sizeof(float[3][4]));
8193 Mem_Free(old.decals);
8194 for (i = 0;i < decalsystem->maxdecals*3;i++)
8195 decalsystem->element3i[i] = i;
8196 if (useshortelements)
8197 for (i = 0;i < decalsystem->maxdecals*3;i++)
8198 decalsystem->element3s[i] = i;
8201 // grab a decal and search for another free slot for the next one
8202 maxdecals = decalsystem->maxdecals;
8203 decals = decalsystem->decals;
8204 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8205 v3f = decalsystem->vertex3f + 9*i;
8206 tc2f = decalsystem->texcoord2f + 6*i;
8207 c4f = decalsystem->color4f + 12*i;
8208 for (i = decalsystem->freedecal;i < maxdecals && decals[i].colors[0][3];i++)
8210 decalsystem->freedecal = i;
8211 if (decalsystem->numdecals <= i)
8212 decalsystem->numdecals = i + 1;
8214 // initialize the decal
8216 decal->triangleindex = triangleindex;
8217 decal->colors[0][0] = (unsigned char)(c0[0]*255.0f);
8218 decal->colors[0][1] = (unsigned char)(c0[1]*255.0f);
8219 decal->colors[0][2] = (unsigned char)(c0[2]*255.0f);
8220 decal->colors[0][3] = 255;
8221 decal->colors[1][0] = (unsigned char)(c1[0]*255.0f);
8222 decal->colors[1][1] = (unsigned char)(c1[1]*255.0f);
8223 decal->colors[1][2] = (unsigned char)(c1[2]*255.0f);
8224 decal->colors[1][3] = 255;
8225 decal->colors[2][0] = (unsigned char)(c2[0]*255.0f);
8226 decal->colors[2][1] = (unsigned char)(c2[1]*255.0f);
8227 decal->colors[2][2] = (unsigned char)(c2[2]*255.0f);
8228 decal->colors[2][3] = 255;
8245 c4f[ 0] = decal->colors[0][0] * ca;
8246 c4f[ 1] = decal->colors[0][1] * ca;
8247 c4f[ 2] = decal->colors[0][2] * ca;
8249 c4f[ 4] = decal->colors[1][0] * ca;
8250 c4f[ 5] = decal->colors[1][1] * ca;
8251 c4f[ 6] = decal->colors[1][2] * ca;
8253 c4f[ 8] = decal->colors[2][0] * ca;
8254 c4f[ 9] = decal->colors[2][1] * ca;
8255 c4f[10] = decal->colors[2][2] * ca;
8259 extern cvar_t cl_decals_bias;
8260 void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
8262 matrix4x4_t projection;
8263 decalsystem_t *decalsystem;
8266 const float *vertex3f;
8267 const msurface_t *surface;
8268 const msurface_t *surfaces;
8269 const int *surfacelist;
8273 int surfacelistindex;
8279 float localorigin[3];
8280 float localnormal[3];
8291 float points[2][9][3];
8296 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8298 R_DecalSystem_Reset(&ent->decalsystem);
8302 decalsystem = &ent->decalsystem;
8303 if (decalsystem->model != model)
8304 R_DecalSystem_Reset(decalsystem);
8305 decalsystem->model = model;
8307 RSurf_ActiveModelEntity(ent, false, false);
8309 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8310 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8311 VectorNormalize(localnormal);
8312 localsize = worldsize*rsurface.inversematrixscale;
8313 ilocalsize = 1.0f / localsize;
8314 localmins[0] = localorigin[0] - localsize;
8315 localmins[1] = localorigin[1] - localsize;
8316 localmins[2] = localorigin[2] - localsize;
8317 localmaxs[0] = localorigin[0] + localsize;
8318 localmaxs[1] = localorigin[1] + localsize;
8319 localmaxs[2] = localorigin[2] + localsize;
8321 //VectorCopy(localnormal, planes[4]);
8322 //VectorVectors(planes[4], planes[2], planes[0]);
8323 AnglesFromVectors(angles, localnormal, NULL, false);
8324 AngleVectors(angles, planes[0], planes[2], planes[4]);
8325 VectorNegate(planes[0], planes[1]);
8326 VectorNegate(planes[2], planes[3]);
8327 VectorNegate(planes[4], planes[5]);
8328 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8329 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8330 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8331 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8332 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8333 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8338 matrix4x4_t forwardprojection;
8339 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8340 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8345 float projectionvector[4][3];
8346 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8347 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8348 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8349 projectionvector[0][0] = planes[0][0] * ilocalsize;
8350 projectionvector[0][1] = planes[1][0] * ilocalsize;
8351 projectionvector[0][2] = planes[2][0] * ilocalsize;
8352 projectionvector[1][0] = planes[0][1] * ilocalsize;
8353 projectionvector[1][1] = planes[1][1] * ilocalsize;
8354 projectionvector[1][2] = planes[2][1] * ilocalsize;
8355 projectionvector[2][0] = planes[0][2] * ilocalsize;
8356 projectionvector[2][1] = planes[1][2] * ilocalsize;
8357 projectionvector[2][2] = planes[2][2] * ilocalsize;
8358 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8359 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8360 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8361 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8365 dynamic = model->surfmesh.isanimated;
8366 vertex3f = rsurface.modelvertex3f;
8367 numsurfacelist = model->nummodelsurfaces;
8368 surfacelist = model->sortedmodelsurfaces;
8369 surfaces = model->data_surfaces;
8370 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8372 surface = surfaces + surfacelist[surfacelistindex];
8373 // skip transparent surfaces
8374 if ((surface->texture->surfaceflags & Q3SURFACEFLAG_NOMARKS) || surface->texture->currentalpha < 1 || (surface->texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)))
8376 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8378 numvertices = surface->num_vertices;
8379 numtriangles = surface->num_triangles;
8380 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8382 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8384 index = 3*e[cornerindex];
8385 VectorCopy(vertex3f + index, v[cornerindex]);
8388 //TriangleNormal(v[0], v[1], v[2], normal);
8389 //if (DotProduct(normal, localnormal) < 0.0f)
8391 // clip by each of the box planes formed from the projection matrix
8392 // if anything survives, we emit the decal
8393 numpoints = PolygonF_Clip(3 , v[0] , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
8394 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
8395 numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
8396 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
8397 numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
8398 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
8401 // some part of the triangle survived, so we have to accept it...
8404 // dynamic always uses the original triangle
8406 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8408 index = 3*e[cornerindex];
8409 VectorCopy(vertex3f + index, v[cornerindex]);
8412 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8414 // convert vertex positions to texcoords
8415 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8416 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8417 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8418 // calculate distance fade from the projection origin
8419 f = a * (1.0f-fabs(temp[0]));
8421 c[cornerindex][0] = r * f;
8422 c[cornerindex][1] = g * f;
8423 c[cornerindex][2] = b * f;
8424 c[cornerindex][3] = 1.0f;
8425 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8428 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex);
8430 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8431 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1);
8436 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
8438 int renderentityindex;
8441 entity_render_t *ent;
8443 worldmins[0] = worldorigin[0] - worldsize;
8444 worldmins[1] = worldorigin[1] - worldsize;
8445 worldmins[2] = worldorigin[2] - worldsize;
8446 worldmaxs[0] = worldorigin[0] + worldsize;
8447 worldmaxs[1] = worldorigin[1] + worldsize;
8448 worldmaxs[2] = worldorigin[2] + worldsize;
8450 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8452 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8454 ent = r_refdef.scene.entities[renderentityindex];
8455 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8458 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8462 extern skinframe_t *decalskinframe;
8463 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8466 decalsystem_t *decalsystem = &ent->decalsystem;
8477 if (!decalsystem->numdecals)
8480 if (r_showsurfaces.integer)
8483 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8485 R_DecalSystem_Reset(decalsystem);
8489 // if the model is static it doesn't matter what value we give for
8490 // wantnormals and wanttangents, so this logic uses only rules applicable
8491 // to a model, knowing that they are meaningless otherwise
8492 if (ent == r_refdef.scene.worldentity)
8493 RSurf_ActiveWorldEntity();
8495 RSurf_ActiveModelEntity(ent, false, false);
8497 if (decalsystem->lastupdatetime)
8498 frametime = cl.time - decalsystem->lastupdatetime;
8501 decalsystem->lastupdatetime = cl.time;
8502 decal = decalsystem->decals;
8503 numdecals = decalsystem->numdecals;
8505 fadedelay = cl_decals_time.value;
8506 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8508 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8510 if (!decal->colors[0][3])
8513 decal->lived += frametime;
8514 if (decal->lived >= fadedelay)
8516 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8519 // kill the decal by zeroing vertex data
8520 memset(decalsystem->vertex3f + 9*i, 0, sizeof(float[3][3]));
8521 memset(decalsystem->texcoord2f + 6*i, 0, sizeof(float[3][2]));
8522 memset(decalsystem->color4f + 12*i, 0, sizeof(float[3][4]));
8523 memset(decal, 0, sizeof(*decal));
8524 if (decalsystem->freedecal > i)
8525 decalsystem->freedecal = i;
8529 // update color values for fading decals
8530 alpha *= (1.0f/255.0f);
8531 c4f = decalsystem->color4f + 12*i;
8532 c4f[ 0] = decal->colors[0][0] * alpha;
8533 c4f[ 1] = decal->colors[0][1] * alpha;
8534 c4f[ 2] = decal->colors[0][2] * alpha;
8536 c4f[ 4] = decal->colors[1][0] * alpha;
8537 c4f[ 5] = decal->colors[1][1] * alpha;
8538 c4f[ 6] = decal->colors[1][2] * alpha;
8540 c4f[ 8] = decal->colors[2][0] * alpha;
8541 c4f[ 9] = decal->colors[2][1] * alpha;
8542 c4f[10] = decal->colors[2][2] * alpha;
8546 // update vertex positions for animated models
8547 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8549 e = rsurface.modelelement3i + 3*decal->triangleindex;
8550 v3f = decalsystem->vertex3f + 9*i;
8551 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8552 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8553 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8557 // reduce numdecals if possible
8558 while (numdecals > 0 && !decalsystem->decals[numdecals - 1].colors[0][3])
8560 decalsystem->numdecals = numdecals;
8564 r_refdef.stats.decals += numdecals;
8565 // now render the decals all at once
8566 // (this assumes they all use one particle font texture!)
8567 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numdecals, decalsystem->element3i, decalsystem->element3s, false, false);
8568 R_Mesh_ResetTextureState();
8569 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8570 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8571 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8572 R_SetupGenericShader(true);
8573 GL_DepthMask(false);
8574 GL_DepthRange(0, 1);
8575 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8577 GL_CullFace(GL_NONE);
8578 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8579 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8580 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8581 GL_LockArrays(0, numdecals * 3);
8582 R_Mesh_Draw(0, numdecals * 3, 0, numdecals, decalsystem->element3i, decalsystem->element3s, 0, 0);
8583 GL_LockArrays(0, 0);
8588 // if there are no decals left, reset decalsystem
8589 R_DecalSystem_Reset(decalsystem);
8593 void R_DrawDebugModel(void)
8595 entity_render_t *ent = rsurface.entity;
8596 int i, j, k, l, flagsmask;
8597 const int *elements;
8599 const msurface_t *surface;
8600 dp_model_t *model = ent->model;
8603 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8605 R_Mesh_ColorPointer(NULL, 0, 0);
8606 R_Mesh_ResetTextureState();
8607 R_SetupGenericShader(false);
8608 GL_DepthRange(0, 1);
8609 GL_DepthTest(!r_showdisabledepthtest.integer);
8610 GL_DepthMask(false);
8611 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8613 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8615 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8616 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8618 if (brush->colbrushf && brush->colbrushf->numtriangles)
8620 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8621 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);
8622 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8625 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8627 if (surface->num_collisiontriangles)
8629 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8630 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);
8631 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8636 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8638 if (r_showtris.integer || r_shownormals.integer)
8640 if (r_showdisabledepthtest.integer)
8642 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8643 GL_DepthMask(false);
8647 GL_BlendFunc(GL_ONE, GL_ZERO);
8650 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8652 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8654 rsurface.texture = R_GetCurrentTexture(surface->texture);
8655 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8657 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8658 if (r_showtris.value > 0)
8660 if (!rsurface.texture->currentlayers->depthmask)
8661 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8662 else if (ent == r_refdef.scene.worldentity)
8663 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8665 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8666 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8667 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8668 R_Mesh_ColorPointer(NULL, 0, 0);
8669 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8670 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8671 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8672 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);
8673 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8676 if (r_shownormals.value < 0)
8679 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8681 VectorCopy(rsurface.vertex3f + l * 3, v);
8682 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8683 qglVertex3f(v[0], v[1], v[2]);
8684 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8685 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8686 qglVertex3f(v[0], v[1], v[2]);
8691 if (r_shownormals.value > 0)
8694 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8696 VectorCopy(rsurface.vertex3f + l * 3, v);
8697 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8698 qglVertex3f(v[0], v[1], v[2]);
8699 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8700 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8701 qglVertex3f(v[0], v[1], v[2]);
8706 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8708 VectorCopy(rsurface.vertex3f + l * 3, v);
8709 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8710 qglVertex3f(v[0], v[1], v[2]);
8711 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8712 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8713 qglVertex3f(v[0], v[1], v[2]);
8718 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8720 VectorCopy(rsurface.vertex3f + l * 3, v);
8721 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8722 qglVertex3f(v[0], v[1], v[2]);
8723 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8724 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8725 qglVertex3f(v[0], v[1], v[2]);
8732 rsurface.texture = NULL;
8736 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8737 int r_maxsurfacelist = 0;
8738 const msurface_t **r_surfacelist = NULL;
8739 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8741 int i, j, endj, f, flagsmask;
8743 dp_model_t *model = r_refdef.scene.worldmodel;
8744 msurface_t *surfaces;
8745 unsigned char *update;
8746 int numsurfacelist = 0;
8750 if (r_maxsurfacelist < model->num_surfaces)
8752 r_maxsurfacelist = model->num_surfaces;
8754 Mem_Free(r_surfacelist);
8755 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8758 RSurf_ActiveWorldEntity();
8760 surfaces = model->data_surfaces;
8761 update = model->brushq1.lightmapupdateflags;
8763 // update light styles on this submodel
8764 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8766 model_brush_lightstyleinfo_t *style;
8767 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8769 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8771 int *list = style->surfacelist;
8772 style->value = r_refdef.scene.lightstylevalue[style->style];
8773 for (j = 0;j < style->numsurfaces;j++)
8774 update[list[j]] = true;
8779 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8784 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8790 rsurface.uselightmaptexture = false;
8791 rsurface.texture = NULL;
8792 rsurface.rtlight = NULL;
8794 // add visible surfaces to draw list
8795 for (i = 0;i < model->nummodelsurfaces;i++)
8797 j = model->sortedmodelsurfaces[i];
8798 if (r_refdef.viewcache.world_surfacevisible[j])
8799 r_surfacelist[numsurfacelist++] = surfaces + j;
8801 // update lightmaps if needed
8803 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8804 if (r_refdef.viewcache.world_surfacevisible[j])
8806 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8807 // don't do anything if there were no surfaces
8808 if (!numsurfacelist)
8810 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8813 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8814 GL_AlphaTest(false);
8816 // add to stats if desired
8817 if (r_speeds.integer && !skysurfaces && !depthonly)
8819 r_refdef.stats.world_surfaces += numsurfacelist;
8820 for (j = 0;j < numsurfacelist;j++)
8821 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8824 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8827 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8829 int i, j, endj, f, flagsmask;
8831 dp_model_t *model = ent->model;
8832 msurface_t *surfaces;
8833 unsigned char *update;
8834 int numsurfacelist = 0;
8838 if (r_maxsurfacelist < model->num_surfaces)
8840 r_maxsurfacelist = model->num_surfaces;
8842 Mem_Free(r_surfacelist);
8843 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8846 // if the model is static it doesn't matter what value we give for
8847 // wantnormals and wanttangents, so this logic uses only rules applicable
8848 // to a model, knowing that they are meaningless otherwise
8849 if (ent == r_refdef.scene.worldentity)
8850 RSurf_ActiveWorldEntity();
8851 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8852 RSurf_ActiveModelEntity(ent, false, false);
8854 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8856 surfaces = model->data_surfaces;
8857 update = model->brushq1.lightmapupdateflags;
8859 // update light styles
8860 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8862 model_brush_lightstyleinfo_t *style;
8863 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8865 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8867 int *list = style->surfacelist;
8868 style->value = r_refdef.scene.lightstylevalue[style->style];
8869 for (j = 0;j < style->numsurfaces;j++)
8870 update[list[j]] = true;
8875 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8880 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8886 rsurface.uselightmaptexture = false;
8887 rsurface.texture = NULL;
8888 rsurface.rtlight = NULL;
8890 // add visible surfaces to draw list
8891 for (i = 0;i < model->nummodelsurfaces;i++)
8892 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8893 // don't do anything if there were no surfaces
8894 if (!numsurfacelist)
8896 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8899 // update lightmaps if needed
8901 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8903 R_BuildLightMap(ent, surfaces + j);
8904 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8905 GL_AlphaTest(false);
8907 // add to stats if desired
8908 if (r_speeds.integer && !skysurfaces && !depthonly)
8910 r_refdef.stats.entities_surfaces += numsurfacelist;
8911 for (j = 0;j < numsurfacelist;j++)
8912 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8915 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8918 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
8920 static texture_t texture;
8921 static msurface_t surface;
8922 const msurface_t *surfacelist = &surface;
8924 // fake enough texture and surface state to render this geometry
8926 texture.update_lastrenderframe = -1; // regenerate this texture
8927 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
8928 texture.currentskinframe = skinframe;
8929 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
8930 texture.specularscalemod = 1;
8931 texture.specularpowermod = 1;
8933 surface.texture = &texture;
8934 surface.num_triangles = numtriangles;
8935 surface.num_firsttriangle = firsttriangle;
8936 surface.num_vertices = numvertices;
8937 surface.num_firstvertex = firstvertex;
8940 rsurface.texture = R_GetCurrentTexture(surface.texture);
8941 rsurface.uselightmaptexture = false;
8942 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);