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", "4", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
89 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
90 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
92 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
93 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
94 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
95 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
96 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
97 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
98 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
99 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
101 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
103 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
104 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
105 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
106 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
107 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
108 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
109 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
110 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
111 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
112 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
113 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
115 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
116 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
117 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
118 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
119 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
121 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
122 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
123 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
124 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
126 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
127 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
128 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
129 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
130 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
131 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
132 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
134 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
135 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
136 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
137 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
139 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
141 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
143 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
145 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
146 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
147 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
148 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
149 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
150 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
151 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
153 extern cvar_t v_glslgamma;
155 extern qboolean v_flipped_state;
157 static struct r_bloomstate_s
162 int bloomwidth, bloomheight;
164 int screentexturewidth, screentextureheight;
165 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
167 int bloomtexturewidth, bloomtextureheight;
168 rtexture_t *texture_bloom;
170 // arrays for rendering the screen passes
171 float screentexcoord2f[8];
172 float bloomtexcoord2f[8];
173 float offsettexcoord2f[8];
175 r_viewport_t viewport;
179 r_waterstate_t r_waterstate;
181 /// shadow volume bsp struct with automatically growing nodes buffer
184 rtexture_t *r_texture_blanknormalmap;
185 rtexture_t *r_texture_white;
186 rtexture_t *r_texture_grey128;
187 rtexture_t *r_texture_black;
188 rtexture_t *r_texture_notexture;
189 rtexture_t *r_texture_whitecube;
190 rtexture_t *r_texture_normalizationcube;
191 rtexture_t *r_texture_fogattenuation;
192 rtexture_t *r_texture_gammaramps;
193 unsigned int r_texture_gammaramps_serial;
194 //rtexture_t *r_texture_fogintensity;
196 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
197 unsigned int r_numqueries;
198 unsigned int r_maxqueries;
200 typedef struct r_qwskincache_s
202 char name[MAX_QPATH];
203 skinframe_t *skinframe;
207 static r_qwskincache_t *r_qwskincache;
208 static int r_qwskincache_size;
210 /// vertex coordinates for a quad that covers the screen exactly
211 const float r_screenvertex3f[12] =
219 extern void R_DrawModelShadows(void);
221 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
224 for (i = 0;i < verts;i++)
235 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
238 for (i = 0;i < verts;i++)
248 // FIXME: move this to client?
251 if (gamemode == GAME_NEHAHRA)
253 Cvar_Set("gl_fogenable", "0");
254 Cvar_Set("gl_fogdensity", "0.2");
255 Cvar_Set("gl_fogred", "0.3");
256 Cvar_Set("gl_foggreen", "0.3");
257 Cvar_Set("gl_fogblue", "0.3");
259 r_refdef.fog_density = 0;
260 r_refdef.fog_red = 0;
261 r_refdef.fog_green = 0;
262 r_refdef.fog_blue = 0;
263 r_refdef.fog_alpha = 1;
264 r_refdef.fog_start = 0;
265 r_refdef.fog_end = 0;
266 r_refdef.fog_height = 1<<30;
267 r_refdef.fog_fadedepth = 128;
270 static void R_BuildBlankTextures(void)
272 unsigned char data[4];
273 data[2] = 128; // normal X
274 data[1] = 128; // normal Y
275 data[0] = 255; // normal Z
276 data[3] = 128; // height
277 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
282 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
287 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
295 static void R_BuildNoTexture(void)
298 unsigned char pix[16][16][4];
299 // this makes a light grey/dark grey checkerboard texture
300 for (y = 0;y < 16;y++)
302 for (x = 0;x < 16;x++)
304 if ((y < 8) ^ (x < 8))
320 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
323 static void R_BuildWhiteCube(void)
325 unsigned char data[6*1*1*4];
326 memset(data, 255, sizeof(data));
327 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
330 static void R_BuildNormalizationCube(void)
334 vec_t s, t, intensity;
336 unsigned char data[6][NORMSIZE][NORMSIZE][4];
337 for (side = 0;side < 6;side++)
339 for (y = 0;y < NORMSIZE;y++)
341 for (x = 0;x < NORMSIZE;x++)
343 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
344 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
379 intensity = 127.0f / sqrt(DotProduct(v, v));
380 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
381 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
382 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
383 data[side][y][x][3] = 255;
387 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
390 static void R_BuildFogTexture(void)
394 unsigned char data1[FOGWIDTH][4];
395 //unsigned char data2[FOGWIDTH][4];
398 r_refdef.fogmasktable_start = r_refdef.fog_start;
399 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
400 r_refdef.fogmasktable_range = r_refdef.fogrange;
401 r_refdef.fogmasktable_density = r_refdef.fog_density;
403 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
404 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
406 d = (x * r - r_refdef.fogmasktable_start);
407 if(developer.integer >= 100)
408 Con_Printf("%f ", d);
410 if (r_fog_exp2.integer)
411 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
413 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
414 if(developer.integer >= 100)
415 Con_Printf(" : %f ", alpha);
416 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
417 if(developer.integer >= 100)
418 Con_Printf(" = %f\n", alpha);
419 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
422 for (x = 0;x < FOGWIDTH;x++)
424 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
429 //data2[x][0] = 255 - b;
430 //data2[x][1] = 255 - b;
431 //data2[x][2] = 255 - b;
434 if (r_texture_fogattenuation)
436 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
437 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
441 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);
442 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
446 static const char *builtinshaderstring =
447 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
448 "// written by Forest 'LordHavoc' Hale\n"
450 "// enable various extensions depending on permutation:\n"
452 "#ifdef USESHADOWMAPRECT\n"
453 "# extension GL_ARB_texture_rectangle : enable\n"
456 "#ifdef USESHADOWMAP2D\n"
457 "# ifdef GL_EXT_gpu_shader4\n"
458 "# extension GL_EXT_gpu_shader4 : enable\n"
460 "# ifdef GL_ARB_texture_gather\n"
461 "# extension GL_ARB_texture_gather : enable\n"
463 "# ifdef GL_AMD_texture_texture4\n"
464 "# extension GL_AMD_texture_texture4 : enable\n"
469 "#ifdef USESHADOWMAPCUBE\n"
470 "# extension GL_EXT_gpu_shader4 : enable\n"
473 "#ifdef USESHADOWSAMPLER\n"
474 "# extension GL_ARB_shadow : enable\n"
477 "// common definitions between vertex shader and fragment shader:\n"
479 "//#ifdef __GLSL_CG_DATA_TYPES\n"
480 "//# define myhalf half\n"
481 "//# define myhalf2 half2\n"
482 "//# define myhalf3half3\n"
483 "//# define myhalf4 half4\n"
485 "# define myhalf float\n"
486 "# define myhalf2 vec2\n"
487 "# define myhalf3 vec3\n"
488 "# define myhalf4 vec4\n"
491 "#ifdef USEFOGINSIDE\n"
494 "# ifdef USEFOGOUTSIDE\n"
499 "#ifdef MODE_DEPTH_OR_SHADOW\n"
501 "# ifdef VERTEX_SHADER\n"
504 " gl_Position = ftransform();\n"
509 "#ifdef MODE_SHOWDEPTH\n"
510 "# ifdef VERTEX_SHADER\n"
513 " gl_Position = ftransform();\n"
514 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
517 "# ifdef FRAGMENT_SHADER\n"
520 " gl_FragColor = gl_Color;\n"
524 "#else // !MODE_SHOWDEPTH\n"
526 "#ifdef MODE_POSTPROCESS\n"
527 "# ifdef VERTEX_SHADER\n"
530 " gl_FrontColor = gl_Color;\n"
531 " gl_Position = ftransform();\n"
532 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
534 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
538 "# ifdef FRAGMENT_SHADER\n"
540 "uniform sampler2D Texture_First;\n"
542 "uniform sampler2D Texture_Second;\n"
544 "#ifdef USEGAMMARAMPS\n"
545 "uniform sampler2D Texture_GammaRamps;\n"
547 "#ifdef USESATURATION\n"
548 "uniform float Saturation;\n"
550 "#ifdef USEVIEWTINT\n"
551 "uniform vec4 TintColor;\n"
553 "//uncomment these if you want to use them:\n"
554 "uniform vec4 UserVec1;\n"
555 "// uniform vec4 UserVec2;\n"
556 "// uniform vec4 UserVec3;\n"
557 "// uniform vec4 UserVec4;\n"
558 "// uniform float ClientTime;\n"
559 "uniform vec2 PixelSize;\n"
562 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
564 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
566 "#ifdef USEVIEWTINT\n"
567 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
570 "#ifdef USEPOSTPROCESSING\n"
571 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
572 "// 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"
573 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
574 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
575 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
576 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
577 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
578 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
581 "#ifdef USESATURATION\n"
582 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
583 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
584 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
585 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
588 "#ifdef USEGAMMARAMPS\n"
589 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
590 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
591 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
598 "#ifdef MODE_GENERIC\n"
599 "# ifdef VERTEX_SHADER\n"
602 " gl_FrontColor = gl_Color;\n"
603 "# ifdef USEDIFFUSE\n"
604 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
606 "# ifdef USESPECULAR\n"
607 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
609 " gl_Position = ftransform();\n"
612 "# ifdef FRAGMENT_SHADER\n"
614 "# ifdef USEDIFFUSE\n"
615 "uniform sampler2D Texture_First;\n"
617 "# ifdef USESPECULAR\n"
618 "uniform sampler2D Texture_Second;\n"
623 " gl_FragColor = gl_Color;\n"
624 "# ifdef USEDIFFUSE\n"
625 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
628 "# ifdef USESPECULAR\n"
629 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
631 "# ifdef USECOLORMAPPING\n"
632 " gl_FragColor *= tex2;\n"
635 " gl_FragColor += tex2;\n"
637 "# ifdef USEVERTEXTEXTUREBLEND\n"
638 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
643 "#else // !MODE_GENERIC\n"
644 "#ifdef MODE_BLOOMBLUR\n"
645 "# ifdef VERTEX_SHADER\n"
648 " gl_FrontColor = gl_Color;\n"
649 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
650 " gl_Position = ftransform();\n"
653 "# ifdef FRAGMENT_SHADER\n"
655 "uniform sampler2D Texture_First;\n"
656 "uniform vec4 BloomBlur_Parameters;\n"
661 " vec2 tc = gl_TexCoord[0].xy;\n"
662 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
663 " tc += BloomBlur_Parameters.xy;\n"
664 " for (i = 1;i < SAMPLES;i++)\n"
666 " color += texture2D(Texture_First, tc).rgb;\n"
667 " tc += BloomBlur_Parameters.xy;\n"
669 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
673 "#else // !MODE_BLOOMBLUR\n"
675 "varying vec2 TexCoord;\n"
676 "#ifdef USEVERTEXTEXTUREBLEND\n"
677 "varying vec2 TexCoord2;\n"
679 "varying vec2 TexCoordLightmap;\n"
681 "#ifdef MODE_LIGHTSOURCE\n"
682 "varying vec3 CubeVector;\n"
685 "#ifdef MODE_LIGHTSOURCE\n"
686 "varying vec3 LightVector;\n"
688 "#ifdef MODE_LIGHTDIRECTION\n"
689 "varying vec3 LightVector;\n"
692 "varying vec3 EyeVector;\n"
694 "varying vec3 EyeVectorModelSpace;\n"
695 "varying float FogPlaneVertexDist;\n"
698 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
699 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
700 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
702 "#ifdef MODE_WATER\n"
703 "varying vec4 ModelViewProjectionPosition;\n"
705 "#ifdef MODE_REFRACTION\n"
706 "varying vec4 ModelViewProjectionPosition;\n"
708 "#ifdef USEREFLECTION\n"
709 "varying vec4 ModelViewProjectionPosition;\n"
716 "// vertex shader specific:\n"
717 "#ifdef VERTEX_SHADER\n"
719 "uniform vec3 LightPosition;\n"
720 "uniform vec3 EyePosition;\n"
721 "uniform vec3 LightDir;\n"
722 "uniform vec4 FogPlane;\n"
724 "// 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"
728 " gl_FrontColor = gl_Color;\n"
729 " // copy the surface texcoord\n"
730 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
731 "#ifdef USEVERTEXTEXTUREBLEND\n"
732 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
734 "#ifndef MODE_LIGHTSOURCE\n"
735 "# ifndef MODE_LIGHTDIRECTION\n"
736 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
740 "#ifdef MODE_LIGHTSOURCE\n"
741 " // transform vertex position into light attenuation/cubemap space\n"
742 " // (-1 to +1 across the light box)\n"
743 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
745 " // transform unnormalized light direction into tangent space\n"
746 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
747 " // normalize it per pixel)\n"
748 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
749 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
750 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
751 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
754 "#ifdef MODE_LIGHTDIRECTION\n"
755 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
756 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
757 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
760 " // transform unnormalized eye direction into tangent space\n"
762 " vec3 EyeVectorModelSpace;\n"
764 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
765 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
766 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
767 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
770 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
773 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
774 " VectorS = gl_MultiTexCoord1.xyz;\n"
775 " VectorT = gl_MultiTexCoord2.xyz;\n"
776 " VectorR = gl_MultiTexCoord3.xyz;\n"
779 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
780 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
781 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
782 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
785 "// transform vertex to camera space, using ftransform to match non-VS\n"
787 " gl_Position = ftransform();\n"
789 "#ifdef MODE_WATER\n"
790 " ModelViewProjectionPosition = gl_Position;\n"
792 "#ifdef MODE_REFRACTION\n"
793 " ModelViewProjectionPosition = gl_Position;\n"
795 "#ifdef USEREFLECTION\n"
796 " ModelViewProjectionPosition = gl_Position;\n"
800 "#endif // VERTEX_SHADER\n"
805 "// fragment shader specific:\n"
806 "#ifdef FRAGMENT_SHADER\n"
808 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
809 "uniform sampler2D Texture_Normal;\n"
810 "uniform sampler2D Texture_Color;\n"
811 "uniform sampler2D Texture_Gloss;\n"
812 "uniform sampler2D Texture_Glow;\n"
813 "uniform sampler2D Texture_SecondaryNormal;\n"
814 "uniform sampler2D Texture_SecondaryColor;\n"
815 "uniform sampler2D Texture_SecondaryGloss;\n"
816 "uniform sampler2D Texture_SecondaryGlow;\n"
817 "uniform sampler2D Texture_Pants;\n"
818 "uniform sampler2D Texture_Shirt;\n"
819 "uniform sampler2D Texture_FogMask;\n"
820 "uniform sampler2D Texture_Lightmap;\n"
821 "uniform sampler2D Texture_Deluxemap;\n"
822 "uniform sampler2D Texture_Refraction;\n"
823 "uniform sampler2D Texture_Reflection;\n"
824 "uniform sampler2D Texture_Attenuation;\n"
825 "uniform samplerCube Texture_Cube;\n"
827 "#define showshadowmap 0\n"
829 "#ifdef USESHADOWMAPRECT\n"
830 "# ifdef USESHADOWSAMPLER\n"
831 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
833 "uniform sampler2DRect Texture_ShadowMapRect;\n"
837 "#ifdef USESHADOWMAP2D\n"
838 "# ifdef USESHADOWSAMPLER\n"
839 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
841 "uniform sampler2D Texture_ShadowMap2D;\n"
845 "#ifdef USESHADOWMAPVSDCT\n"
846 "uniform samplerCube Texture_CubeProjection;\n"
849 "#ifdef USESHADOWMAPCUBE\n"
850 "# ifdef USESHADOWSAMPLER\n"
851 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
853 "uniform samplerCube Texture_ShadowMapCube;\n"
857 "uniform myhalf3 LightColor;\n"
858 "uniform myhalf3 AmbientColor;\n"
859 "uniform myhalf3 DiffuseColor;\n"
860 "uniform myhalf3 SpecularColor;\n"
861 "uniform myhalf3 Color_Pants;\n"
862 "uniform myhalf3 Color_Shirt;\n"
863 "uniform myhalf3 FogColor;\n"
865 "uniform myhalf4 TintColor;\n"
868 "//#ifdef MODE_WATER\n"
869 "uniform vec4 DistortScaleRefractReflect;\n"
870 "uniform vec4 ScreenScaleRefractReflect;\n"
871 "uniform vec4 ScreenCenterRefractReflect;\n"
872 "uniform myhalf4 RefractColor;\n"
873 "uniform myhalf4 ReflectColor;\n"
874 "uniform myhalf ReflectFactor;\n"
875 "uniform myhalf ReflectOffset;\n"
877 "//# ifdef MODE_REFRACTION\n"
878 "//uniform vec4 DistortScaleRefractReflect;\n"
879 "//uniform vec4 ScreenScaleRefractReflect;\n"
880 "//uniform vec4 ScreenCenterRefractReflect;\n"
881 "//uniform myhalf4 RefractColor;\n"
882 "//# ifdef USEREFLECTION\n"
883 "//uniform myhalf4 ReflectColor;\n"
886 "//# ifdef USEREFLECTION\n"
887 "//uniform vec4 DistortScaleRefractReflect;\n"
888 "//uniform vec4 ScreenScaleRefractReflect;\n"
889 "//uniform vec4 ScreenCenterRefractReflect;\n"
890 "//uniform myhalf4 ReflectColor;\n"
895 "uniform myhalf3 GlowColor;\n"
896 "uniform myhalf SceneBrightness;\n"
898 "uniform float OffsetMapping_Scale;\n"
899 "uniform float OffsetMapping_Bias;\n"
900 "uniform float FogRangeRecip;\n"
901 "uniform float FogPlaneViewDist;\n"
902 "uniform float FogHeightFade;\n"
904 "uniform myhalf AmbientScale;\n"
905 "uniform myhalf DiffuseScale;\n"
906 "uniform myhalf SpecularScale;\n"
907 "uniform myhalf SpecularPower;\n"
909 "#ifdef USEOFFSETMAPPING\n"
910 "vec2 OffsetMapping(vec2 TexCoord)\n"
912 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
913 " // 14 sample relief mapping: linear search and then binary search\n"
914 " // this basically steps forward a small amount repeatedly until it finds\n"
915 " // itself inside solid, then jitters forward and back using decreasing\n"
916 " // amounts to find the impact\n"
917 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
918 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
919 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
920 " vec3 RT = vec3(TexCoord, 1);\n"
921 " OffsetVector *= 0.1;\n"
922 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
923 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
932 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
933 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
934 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
935 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
938 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
939 " // this basically moves forward the full distance, and then backs up based\n"
940 " // on height of samples\n"
941 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
942 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
943 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
944 " TexCoord += OffsetVector;\n"
945 " OffsetVector *= 0.333;\n"
946 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
947 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
948 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
949 " return TexCoord;\n"
952 "#endif // USEOFFSETMAPPING\n"
954 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
955 "uniform vec2 ShadowMap_TextureScale;\n"
956 "uniform vec4 ShadowMap_Parameters;\n"
959 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
960 "vec3 GetShadowMapTC2D(vec3 dir)\n"
962 " vec3 adir = abs(dir);\n"
963 "# ifndef USESHADOWMAPVSDCT\n"
967 " if (adir.x > adir.y)\n"
969 " if (adir.x > adir.z) // X\n"
973 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
979 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
984 " if (adir.y > adir.z) // Y\n"
988 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
994 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
998 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
999 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1000 " stc.z += ShadowMap_Parameters.z;\n"
1001 "# if showshadowmap\n"
1002 " stc.xy *= ShadowMap_TextureScale;\n"
1006 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1007 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1008 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1009 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1010 " stc.z += ShadowMap_Parameters.z;\n"
1011 "# if showshadowmap\n"
1012 " stc.xy *= ShadowMap_TextureScale;\n"
1017 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1019 "#ifdef USESHADOWMAPCUBE\n"
1020 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1022 " vec3 adir = abs(dir);\n"
1023 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1027 "#if !showshadowmap\n"
1028 "# ifdef USESHADOWMAPRECT\n"
1029 "float ShadowMapCompare(vec3 dir)\n"
1031 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1033 "# ifdef USESHADOWSAMPLER\n"
1035 "# ifdef USESHADOWMAPPCF\n"
1036 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1037 " 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"
1039 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1044 "# ifdef USESHADOWMAPPCF\n"
1045 "# if USESHADOWMAPPCF > 1\n"
1046 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1047 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1048 " 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"
1049 " 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"
1050 " 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"
1051 " 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"
1052 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1053 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1055 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1056 " vec2 offset = fract(shadowmaptc.xy);\n"
1057 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1058 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1059 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1060 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1061 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1064 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1072 "# ifdef USESHADOWMAP2D\n"
1073 "float ShadowMapCompare(vec3 dir)\n"
1075 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1078 "# ifdef USESHADOWSAMPLER\n"
1079 "# ifdef USESHADOWMAPPCF\n"
1080 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1081 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1082 " 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"
1084 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1087 "# ifdef USESHADOWMAPPCF\n"
1088 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1089 "# ifdef GL_ARB_texture_gather\n"
1090 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1092 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1094 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1095 " center *= ShadowMap_TextureScale;\n"
1096 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1097 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1098 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1099 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1100 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1101 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1102 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1104 "# ifdef GL_EXT_gpu_shader4\n"
1105 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1107 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1109 "# if USESHADOWMAPPCF > 1\n"
1110 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1111 " center *= ShadowMap_TextureScale;\n"
1112 " 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"
1113 " 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"
1114 " 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"
1115 " 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"
1116 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1117 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1119 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1120 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1121 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1122 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1123 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1124 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1128 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1135 "# ifdef USESHADOWMAPCUBE\n"
1136 "float ShadowMapCompare(vec3 dir)\n"
1138 " // apply depth texture cubemap as light filter\n"
1139 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1141 "# ifdef USESHADOWSAMPLER\n"
1142 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1144 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1151 "#ifdef MODE_WATER\n"
1156 "#ifdef USEOFFSETMAPPING\n"
1157 " // apply offsetmapping\n"
1158 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1159 "#define TexCoord TexCoordOffset\n"
1162 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1163 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1164 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1165 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1166 " // FIXME temporary hack to detect the case that the reflection\n"
1167 " // gets blackened at edges due to leaving the area that contains actual\n"
1169 " // Remove this 'ack once we have a better way to stop this thing from\n"
1171 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1172 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1173 " 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 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1176 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1177 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\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 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1181 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1182 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1185 "#else // !MODE_WATER\n"
1186 "#ifdef MODE_REFRACTION\n"
1188 "// refraction pass\n"
1191 "#ifdef USEOFFSETMAPPING\n"
1192 " // apply offsetmapping\n"
1193 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1194 "#define TexCoord TexCoordOffset\n"
1197 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1198 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1199 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1200 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1201 " // FIXME temporary hack to detect the case that the reflection\n"
1202 " // gets blackened at edges due to leaving the area that contains actual\n"
1204 " // Remove this 'ack once we have a better way to stop this thing from\n"
1206 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1207 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1208 " 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 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1211 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1214 "#else // !MODE_REFRACTION\n"
1217 "#ifdef USEOFFSETMAPPING\n"
1218 " // apply offsetmapping\n"
1219 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1220 "#define TexCoord TexCoordOffset\n"
1223 " // combine the diffuse textures (base, pants, shirt)\n"
1224 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1225 "#ifdef USECOLORMAPPING\n"
1226 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1228 "#ifdef USEVERTEXTEXTUREBLEND\n"
1229 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1230 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1231 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1232 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1234 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1237 "#ifdef USEDIFFUSE\n"
1238 " // get the surface normal and the gloss color\n"
1239 "# ifdef USEVERTEXTEXTUREBLEND\n"
1240 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1241 "# ifdef USESPECULAR\n"
1242 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1245 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1246 "# ifdef USESPECULAR\n"
1247 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1254 "#ifdef MODE_LIGHTSOURCE\n"
1255 " // light source\n"
1257 " // calculate surface normal, light normal, and specular normal\n"
1258 " // compute color intensity for the two textures (colormap and glossmap)\n"
1259 " // scale by light color and attenuation as efficiently as possible\n"
1260 " // (do as much scalar math as possible rather than vector math)\n"
1261 "# ifdef USEDIFFUSE\n"
1262 " // get the light normal\n"
1263 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1265 "# ifdef USESPECULAR\n"
1266 "# ifndef USEEXACTSPECULARMATH\n"
1267 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1270 " // calculate directional shading\n"
1271 "# ifdef USEEXACTSPECULARMATH\n"
1272 " 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"
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(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n"
1277 "# ifdef USEDIFFUSE\n"
1278 " // calculate directional shading\n"
1279 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1281 " // calculate directionless shading\n"
1282 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1286 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1287 "#if !showshadowmap\n"
1288 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1292 "# ifdef USECUBEFILTER\n"
1293 " // apply light cubemap filter\n"
1294 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1295 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1297 "#endif // MODE_LIGHTSOURCE\n"
1302 "#ifdef MODE_LIGHTDIRECTION\n"
1303 " // directional model lighting\n"
1304 "# ifdef USEDIFFUSE\n"
1305 " // get the light normal\n"
1306 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1308 "# ifdef USESPECULAR\n"
1309 " // calculate directional shading\n"
1310 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1311 "# ifdef USEEXACTSPECULARMATH\n"
1312 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1314 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1315 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1318 "# ifdef USEDIFFUSE\n"
1320 " // calculate directional shading\n"
1321 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1323 " color.rgb *= AmbientColor;\n"
1326 "#endif // MODE_LIGHTDIRECTION\n"
1331 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1332 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1334 " // get the light normal\n"
1335 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1336 " myhalf3 diffusenormal;\n"
1337 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1338 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1339 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1340 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1341 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1342 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1343 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1344 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1345 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1346 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1347 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1348 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1349 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1350 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1351 "# ifdef USESPECULAR\n"
1352 "# ifdef USEEXACTSPECULARMATH\n"
1353 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1355 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1356 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1360 " // apply lightmap color\n"
1361 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1362 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1367 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1368 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1370 " // get the light normal\n"
1371 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1372 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1373 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1374 "# ifdef USESPECULAR\n"
1375 "# ifdef USEEXACTSPECULARMATH\n"
1376 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1378 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1379 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1383 " // apply lightmap color\n"
1384 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1385 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1390 "#ifdef MODE_LIGHTMAP\n"
1391 " // apply lightmap color\n"
1392 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1393 "#endif // MODE_LIGHTMAP\n"
1398 "#ifdef MODE_VERTEXCOLOR\n"
1399 " // apply lightmap color\n"
1400 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1401 "#endif // MODE_VERTEXCOLOR\n"
1406 "#ifdef MODE_FLATCOLOR\n"
1407 "#endif // MODE_FLATCOLOR\n"
1415 " color *= TintColor;\n"
1418 "#ifdef USEVERTEXTEXTUREBLEND\n"
1419 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1421 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1425 " color.rgb *= SceneBrightness;\n"
1427 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1430 "#ifdef USEFOGOUTSIDE\n"
1431 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1433 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1435 "// float FogHeightFade1 = -0.5/1024.0;\n"
1436 "// if (FogPlaneViewDist >= 0.0)\n"
1437 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade1);\n"
1439 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade1);\n"
1440 "//# ifdef USEFOGABOVE\n"
1441 "// if (FogPlaneViewDist >= 0.0)\n"
1442 "// fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist);\n"
1444 "// fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist));\n"
1445 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1446 "// fogfrac *= min(1.0, (max(0.0, fade*FogPlaneVertexDist) + max(0.0, fade*FogPlaneViewDist)));\n"
1447 "// fogfrac *= min(1.0, (max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist)));\n"
1448 "// fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist))*FogHeightFade1);\n"
1450 " //fogfrac *= min(1.0, max(0.0, (max(-2048, min(0, FogPlaneVertexDist)) + max(-2048, min(0, FogPlaneViewDist)))/-2048.0));\n"
1451 " //float fade = -0.5/128.0;\n"
1452 " //fogfrac *= max(0.0, min(1.0, fade*FogPlaneVertexDist)) + max(0.0, min(1.0, fade*FogPlaneViewDist));\n"
1453 " //fogfrac *= max(0.0, min(1.0, FogHeightFade1*FogPlaneVertexDist)) + max(0.0, min(1.0, FogHeightFade1*FogPlaneViewDist));\n"
1454 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist)) + min(1.0, max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1455 " //fogfrac *= min(1.0, max(0.0, FogHeightFade1*FogPlaneVertexDist) + max(0.0, FogHeightFade1*FogPlaneViewDist));\n"
1456 " //fogfrac *= min(1.0, 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(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1459 " //fogfrac *= min(1.0, (min(0.0, FogPlaneVertexDist) + min(0.0, FogPlaneViewDist)) * FogHeightFade1);\n"
1461 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0))));\n"
1464 " // 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"
1465 "#ifdef USEREFLECTION\n"
1466 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1467 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1468 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1469 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1470 " // FIXME temporary hack to detect the case that the reflection\n"
1471 " // gets blackened at edges due to leaving the area that contains actual\n"
1473 " // Remove this 'ack once we have a better way to stop this thing from\n"
1475 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1476 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1477 " 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 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1480 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1483 " gl_FragColor = vec4(color);\n"
1485 "#if showshadowmap\n"
1486 "# ifdef USESHADOWMAPRECT\n"
1487 "# ifdef USESHADOWSAMPLER\n"
1488 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1490 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1493 "# ifdef USESHADOWMAP2D\n"
1494 "# ifdef USESHADOWSAMPLER\n"
1495 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1497 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1501 "# ifdef USESHADOWMAPCUBE\n"
1502 "# ifdef USESHADOWSAMPLER\n"
1503 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1505 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1510 "#endif // !MODE_REFRACTION\n"
1511 "#endif // !MODE_WATER\n"
1513 "#endif // FRAGMENT_SHADER\n"
1515 "#endif // !MODE_BLOOMBLUR\n"
1516 "#endif // !MODE_GENERIC\n"
1517 "#endif // !MODE_POSTPROCESS\n"
1518 "#endif // !MODE_SHOWDEPTH\n"
1519 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1522 typedef struct shaderpermutationinfo_s
1524 const char *pretext;
1527 shaderpermutationinfo_t;
1529 typedef struct shadermodeinfo_s
1531 const char *vertexfilename;
1532 const char *geometryfilename;
1533 const char *fragmentfilename;
1534 const char *pretext;
1539 typedef enum shaderpermutation_e
1541 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1542 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1543 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1544 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1545 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1546 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1547 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1548 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1549 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1550 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1551 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1552 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1553 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1554 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1555 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1556 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1557 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1558 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1559 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1560 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1561 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1562 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1563 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1564 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1565 SHADERPERMUTATION_LIMIT = 1<<24, ///< size of permutations array
1566 SHADERPERMUTATION_COUNT = 24 ///< size of shaderpermutationinfo array
1568 shaderpermutation_t;
1570 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1571 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1573 {"#define USEDIFFUSE\n", " diffuse"},
1574 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1575 {"#define USEVIEWTINT\n", " viewtint"},
1576 {"#define USECOLORMAPPING\n", " colormapping"},
1577 {"#define USESATURATION\n", " saturation"},
1578 {"#define USEFOGINSIDE\n", " foginside"},
1579 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1580 {"#define USEGAMMARAMPS\n", " gammaramps"},
1581 {"#define USECUBEFILTER\n", " cubefilter"},
1582 {"#define USEGLOW\n", " glow"},
1583 {"#define USEBLOOM\n", " bloom"},
1584 {"#define USESPECULAR\n", " specular"},
1585 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1586 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1587 {"#define USEREFLECTION\n", " reflection"},
1588 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1589 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1590 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1591 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1592 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1593 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1594 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1595 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1596 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1599 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1600 typedef enum shadermode_e
1602 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1603 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1604 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1605 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1606 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1607 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1608 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1609 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1610 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1611 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1612 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1613 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1614 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1619 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1620 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1622 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1623 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1624 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1625 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1626 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1627 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1628 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1629 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1630 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1631 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1632 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1633 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1634 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1637 struct r_glsl_permutation_s;
1638 typedef struct r_glsl_permutation_s
1640 /// hash lookup data
1641 struct r_glsl_permutation_s *hashnext;
1643 unsigned int permutation;
1645 /// indicates if we have tried compiling this permutation already
1647 /// 0 if compilation failed
1649 /// locations of detected uniforms in program object, or -1 if not found
1650 int loc_Texture_First;
1651 int loc_Texture_Second;
1652 int loc_Texture_GammaRamps;
1653 int loc_Texture_Normal;
1654 int loc_Texture_Color;
1655 int loc_Texture_Gloss;
1656 int loc_Texture_Glow;
1657 int loc_Texture_SecondaryNormal;
1658 int loc_Texture_SecondaryColor;
1659 int loc_Texture_SecondaryGloss;
1660 int loc_Texture_SecondaryGlow;
1661 int loc_Texture_Pants;
1662 int loc_Texture_Shirt;
1663 int loc_Texture_FogMask;
1664 int loc_Texture_Lightmap;
1665 int loc_Texture_Deluxemap;
1666 int loc_Texture_Attenuation;
1667 int loc_Texture_Cube;
1668 int loc_Texture_Refraction;
1669 int loc_Texture_Reflection;
1670 int loc_Texture_ShadowMapRect;
1671 int loc_Texture_ShadowMapCube;
1672 int loc_Texture_ShadowMap2D;
1673 int loc_Texture_CubeProjection;
1675 int loc_LightPosition;
1676 int loc_EyePosition;
1677 int loc_Color_Pants;
1678 int loc_Color_Shirt;
1680 int loc_FogPlaneViewDist;
1681 int loc_FogRangeRecip;
1682 int loc_FogHeightFade;
1683 int loc_AmbientScale;
1684 int loc_DiffuseScale;
1685 int loc_SpecularScale;
1686 int loc_SpecularPower;
1688 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1689 int loc_OffsetMapping_Scale;
1691 int loc_AmbientColor;
1692 int loc_DiffuseColor;
1693 int loc_SpecularColor;
1695 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1696 int loc_GammaCoeff; ///< 1 / gamma
1697 int loc_DistortScaleRefractReflect;
1698 int loc_ScreenScaleRefractReflect;
1699 int loc_ScreenCenterRefractReflect;
1700 int loc_RefractColor;
1701 int loc_ReflectColor;
1702 int loc_ReflectFactor;
1703 int loc_ReflectOffset;
1711 int loc_ShadowMap_TextureScale;
1712 int loc_ShadowMap_Parameters;
1714 r_glsl_permutation_t;
1716 #define SHADERPERMUTATION_HASHSIZE 4096
1718 /// information about each possible shader permutation
1719 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1720 /// currently selected permutation
1721 r_glsl_permutation_t *r_glsl_permutation;
1722 /// storage for permutations linked in the hash table
1723 memexpandablearray_t r_glsl_permutationarray;
1725 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1727 //unsigned int hashdepth = 0;
1728 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1729 r_glsl_permutation_t *p;
1730 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1732 if (p->mode == mode && p->permutation == permutation)
1734 //if (hashdepth > 10)
1735 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1740 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1742 p->permutation = permutation;
1743 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1744 r_glsl_permutationhash[mode][hashindex] = p;
1745 //if (hashdepth > 10)
1746 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1750 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1753 if (!filename || !filename[0])
1755 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1758 if (printfromdisknotice)
1759 Con_DPrint("from disk... ");
1760 return shaderstring;
1762 else if (!strcmp(filename, "glsl/default.glsl"))
1764 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1765 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1767 return shaderstring;
1770 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1773 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1774 int vertstrings_count = 0;
1775 int geomstrings_count = 0;
1776 int fragstrings_count = 0;
1777 char *vertexstring, *geometrystring, *fragmentstring;
1778 const char *vertstrings_list[32+3];
1779 const char *geomstrings_list[32+3];
1780 const char *fragstrings_list[32+3];
1781 char permutationname[256];
1788 permutationname[0] = 0;
1789 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1790 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1791 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1793 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1795 // the first pretext is which type of shader to compile as
1796 // (later these will all be bound together as a program object)
1797 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1798 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1799 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1801 // the second pretext is the mode (for example a light source)
1802 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1803 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1804 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1805 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1807 // now add all the permutation pretexts
1808 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1810 if (permutation & (1<<i))
1812 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1813 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1814 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1815 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1819 // keep line numbers correct
1820 vertstrings_list[vertstrings_count++] = "\n";
1821 geomstrings_list[geomstrings_count++] = "\n";
1822 fragstrings_list[fragstrings_count++] = "\n";
1826 // now append the shader text itself
1827 vertstrings_list[vertstrings_count++] = vertexstring;
1828 geomstrings_list[geomstrings_count++] = geometrystring;
1829 fragstrings_list[fragstrings_count++] = fragmentstring;
1831 // if any sources were NULL, clear the respective list
1833 vertstrings_count = 0;
1834 if (!geometrystring)
1835 geomstrings_count = 0;
1836 if (!fragmentstring)
1837 fragstrings_count = 0;
1839 // compile the shader program
1840 if (vertstrings_count + geomstrings_count + fragstrings_count)
1841 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1845 qglUseProgramObjectARB(p->program);CHECKGLERROR
1846 // look up all the uniform variable names we care about, so we don't
1847 // have to look them up every time we set them
1848 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1849 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1850 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1851 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1852 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1853 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1854 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1855 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1856 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1857 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1858 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1859 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1860 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1861 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1862 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1863 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1864 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1865 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1866 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1867 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1868 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1869 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1870 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1871 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1872 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1873 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1874 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1875 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1876 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1877 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
1878 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
1879 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1880 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
1881 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1882 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1883 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1884 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1885 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1886 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1887 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1888 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1889 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1890 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1891 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1892 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1893 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1894 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1895 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1896 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1897 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1898 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1899 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1900 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1901 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1902 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1903 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1904 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1905 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1906 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1907 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1908 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1909 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1910 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1911 // initialize the samplers to refer to the texture units we use
1912 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1913 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1914 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1915 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1916 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1917 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1918 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1919 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1920 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1921 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1922 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1923 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1924 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1925 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1926 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1927 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1928 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1929 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1930 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1931 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1932 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1933 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1934 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1935 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1937 if (developer.integer)
1938 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1941 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1945 Mem_Free(vertexstring);
1947 Mem_Free(geometrystring);
1949 Mem_Free(fragmentstring);
1952 void R_GLSL_Restart_f(void)
1954 unsigned int i, limit;
1955 r_glsl_permutation_t *p;
1956 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1957 for (i = 0;i < limit;i++)
1959 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1961 GL_Backend_FreeProgram(p->program);
1962 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1965 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1968 void R_GLSL_DumpShader_f(void)
1972 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1975 Con_Printf("failed to write to glsl/default.glsl\n");
1979 FS_Print(file, "/* The engine may define the following macros:\n");
1980 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1981 for (i = 0;i < SHADERMODE_COUNT;i++)
1982 FS_Print(file, shadermodeinfo[i].pretext);
1983 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1984 FS_Print(file, shaderpermutationinfo[i].pretext);
1985 FS_Print(file, "*/\n");
1986 FS_Print(file, builtinshaderstring);
1989 Con_Printf("glsl/default.glsl written\n");
1992 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1994 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1995 if (r_glsl_permutation != perm)
1997 r_glsl_permutation = perm;
1998 if (!r_glsl_permutation->program)
2000 if (!r_glsl_permutation->compiled)
2001 R_GLSL_CompilePermutation(perm, mode, permutation);
2002 if (!r_glsl_permutation->program)
2004 // remove features until we find a valid permutation
2006 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2008 // reduce i more quickly whenever it would not remove any bits
2009 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2010 if (!(permutation & j))
2013 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2014 if (!r_glsl_permutation->compiled)
2015 R_GLSL_CompilePermutation(perm, mode, permutation);
2016 if (r_glsl_permutation->program)
2019 if (i >= SHADERPERMUTATION_COUNT)
2021 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");
2022 Cvar_SetValueQuick(&r_glsl, 0);
2023 R_GLSL_Restart_f(); // unload shaders
2024 return; // no bit left to clear
2029 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2033 void R_SetupGenericShader(qboolean usetexture)
2035 if (gl_support_fragment_shader)
2037 if (r_glsl.integer && r_glsl_usegeneric.integer)
2038 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2039 else if (r_glsl_permutation)
2041 r_glsl_permutation = NULL;
2042 qglUseProgramObjectARB(0);CHECKGLERROR
2047 void R_SetupGenericTwoTextureShader(int texturemode)
2049 if (gl_support_fragment_shader)
2051 if (r_glsl.integer && r_glsl_usegeneric.integer)
2052 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))));
2053 else if (r_glsl_permutation)
2055 r_glsl_permutation = NULL;
2056 qglUseProgramObjectARB(0);CHECKGLERROR
2059 if (!r_glsl_permutation)
2061 if (texturemode == GL_DECAL && gl_combine.integer)
2062 texturemode = GL_INTERPOLATE_ARB;
2063 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
2067 void R_SetupDepthOrShadowShader(void)
2069 if (gl_support_fragment_shader)
2071 if (r_glsl.integer && r_glsl_usegeneric.integer)
2072 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2073 else if (r_glsl_permutation)
2075 r_glsl_permutation = NULL;
2076 qglUseProgramObjectARB(0);CHECKGLERROR
2081 void R_SetupShowDepthShader(void)
2083 if (gl_support_fragment_shader)
2085 if (r_glsl.integer && r_glsl_usegeneric.integer)
2086 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2087 else if (r_glsl_permutation)
2089 r_glsl_permutation = NULL;
2090 qglUseProgramObjectARB(0);CHECKGLERROR
2095 extern rtexture_t *r_shadow_attenuationgradienttexture;
2096 extern rtexture_t *r_shadow_attenuation2dtexture;
2097 extern rtexture_t *r_shadow_attenuation3dtexture;
2098 extern qboolean r_shadow_usingshadowmaprect;
2099 extern qboolean r_shadow_usingshadowmapcube;
2100 extern qboolean r_shadow_usingshadowmap2d;
2101 extern float r_shadow_shadowmap_texturescale[2];
2102 extern float r_shadow_shadowmap_parameters[4];
2103 extern qboolean r_shadow_shadowmapvsdct;
2104 extern qboolean r_shadow_shadowmapsampler;
2105 extern int r_shadow_shadowmappcf;
2106 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2108 // select a permutation of the lighting shader appropriate to this
2109 // combination of texture, entity, light source, and fogging, only use the
2110 // minimum features necessary to avoid wasting rendering time in the
2111 // fragment shader on features that are not being used
2112 unsigned int permutation = 0;
2113 unsigned int mode = 0;
2114 // TODO: implement geometry-shader based shadow volumes someday
2115 if (r_glsl_offsetmapping.integer)
2117 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2118 if (r_glsl_offsetmapping_reliefmapping.integer)
2119 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2121 if (rsurfacepass == RSURFPASS_BACKGROUND)
2123 // distorted background
2124 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2125 mode = SHADERMODE_WATER;
2127 mode = SHADERMODE_REFRACTION;
2129 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2132 mode = SHADERMODE_LIGHTSOURCE;
2133 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2134 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2135 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2136 permutation |= SHADERPERMUTATION_CUBEFILTER;
2137 if (diffusescale > 0)
2138 permutation |= SHADERPERMUTATION_DIFFUSE;
2139 if (specularscale > 0)
2140 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2141 if (r_refdef.fogenabled)
2142 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2143 if (rsurface.texture->colormapping)
2144 permutation |= SHADERPERMUTATION_COLORMAPPING;
2145 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2147 if (r_shadow_usingshadowmaprect)
2148 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2149 if (r_shadow_usingshadowmap2d)
2150 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2151 if (r_shadow_usingshadowmapcube)
2152 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2153 else if(r_shadow_shadowmapvsdct)
2154 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2156 if (r_shadow_shadowmapsampler)
2157 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2158 if (r_shadow_shadowmappcf > 1)
2159 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2160 else if (r_shadow_shadowmappcf)
2161 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2164 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2166 // unshaded geometry (fullbright or ambient model lighting)
2167 mode = SHADERMODE_FLATCOLOR;
2168 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2169 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2170 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2171 permutation |= SHADERPERMUTATION_GLOW;
2172 if (r_refdef.fogenabled)
2173 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2174 if (rsurface.texture->colormapping)
2175 permutation |= SHADERPERMUTATION_COLORMAPPING;
2176 if (r_glsl_offsetmapping.integer)
2178 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2179 if (r_glsl_offsetmapping_reliefmapping.integer)
2180 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2182 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2183 permutation |= SHADERPERMUTATION_REFLECTION;
2185 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2187 // directional model lighting
2188 mode = SHADERMODE_LIGHTDIRECTION;
2189 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2190 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2191 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2192 permutation |= SHADERPERMUTATION_GLOW;
2193 permutation |= SHADERPERMUTATION_DIFFUSE;
2194 if (specularscale > 0)
2195 permutation |= SHADERPERMUTATION_SPECULAR;
2196 if (r_refdef.fogenabled)
2197 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2198 if (rsurface.texture->colormapping)
2199 permutation |= SHADERPERMUTATION_COLORMAPPING;
2200 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2201 permutation |= SHADERPERMUTATION_REFLECTION;
2203 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2205 // ambient model lighting
2206 mode = SHADERMODE_LIGHTDIRECTION;
2207 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2208 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2209 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2210 permutation |= SHADERPERMUTATION_GLOW;
2211 if (r_refdef.fogenabled)
2212 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2213 if (rsurface.texture->colormapping)
2214 permutation |= SHADERPERMUTATION_COLORMAPPING;
2215 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2216 permutation |= SHADERPERMUTATION_REFLECTION;
2221 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2223 // deluxemapping (light direction texture)
2224 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2225 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2227 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2228 permutation |= SHADERPERMUTATION_DIFFUSE;
2229 if (specularscale > 0)
2230 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2232 else if (r_glsl_deluxemapping.integer >= 2)
2234 // fake deluxemapping (uniform light direction in tangentspace)
2235 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2236 permutation |= SHADERPERMUTATION_DIFFUSE;
2237 if (specularscale > 0)
2238 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2240 else if (rsurface.uselightmaptexture)
2242 // ordinary lightmapping (q1bsp, q3bsp)
2243 mode = SHADERMODE_LIGHTMAP;
2247 // ordinary vertex coloring (q3bsp)
2248 mode = SHADERMODE_VERTEXCOLOR;
2250 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2251 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2252 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2253 permutation |= SHADERPERMUTATION_GLOW;
2254 if (r_refdef.fogenabled)
2255 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2256 if (rsurface.texture->colormapping)
2257 permutation |= SHADERPERMUTATION_COLORMAPPING;
2258 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2259 permutation |= SHADERPERMUTATION_REFLECTION;
2261 if(permutation & SHADERPERMUTATION_SPECULAR)
2262 if(r_shadow_glossexact.integer)
2263 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2264 R_SetupShader_SetPermutation(mode, permutation);
2265 if (mode == SHADERMODE_LIGHTSOURCE)
2267 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2268 if (permutation & SHADERPERMUTATION_DIFFUSE)
2270 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2271 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2272 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2273 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2277 // ambient only is simpler
2278 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]);
2279 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2280 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2281 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2283 // additive passes are only darkened by fog, not tinted
2284 if (r_glsl_permutation->loc_FogColor >= 0)
2285 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2286 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]);
2287 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]);
2291 if (mode == SHADERMODE_LIGHTDIRECTION)
2293 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);
2294 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);
2295 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);
2296 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]);
2300 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2301 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2302 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2304 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]);
2305 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);
2306 // additive passes are only darkened by fog, not tinted
2307 if (r_glsl_permutation->loc_FogColor >= 0)
2309 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2310 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2312 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2314 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);
2315 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]);
2316 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]);
2317 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2318 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2319 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2320 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2322 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2323 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2324 if (r_glsl_permutation->loc_Color_Pants >= 0)
2326 if (rsurface.texture->currentskinframe->pants)
2327 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2329 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2331 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2333 if (rsurface.texture->currentskinframe->shirt)
2334 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2336 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2338 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]);
2339 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2340 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2341 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2342 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2344 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2348 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2350 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2354 #define SKINFRAME_HASH 1024
2358 int loadsequence; // incremented each level change
2359 memexpandablearray_t array;
2360 skinframe_t *hash[SKINFRAME_HASH];
2363 r_skinframe_t r_skinframe;
2365 void R_SkinFrame_PrepareForPurge(void)
2367 r_skinframe.loadsequence++;
2368 // wrap it without hitting zero
2369 if (r_skinframe.loadsequence >= 200)
2370 r_skinframe.loadsequence = 1;
2373 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2377 // mark the skinframe as used for the purging code
2378 skinframe->loadsequence = r_skinframe.loadsequence;
2381 void R_SkinFrame_Purge(void)
2385 for (i = 0;i < SKINFRAME_HASH;i++)
2387 for (s = r_skinframe.hash[i];s;s = s->next)
2389 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2391 if (s->merged == s->base)
2393 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2394 R_PurgeTexture(s->stain );s->stain = NULL;
2395 R_PurgeTexture(s->merged);s->merged = NULL;
2396 R_PurgeTexture(s->base );s->base = NULL;
2397 R_PurgeTexture(s->pants );s->pants = NULL;
2398 R_PurgeTexture(s->shirt );s->shirt = NULL;
2399 R_PurgeTexture(s->nmap );s->nmap = NULL;
2400 R_PurgeTexture(s->gloss );s->gloss = NULL;
2401 R_PurgeTexture(s->glow );s->glow = NULL;
2402 R_PurgeTexture(s->fog );s->fog = NULL;
2403 s->loadsequence = 0;
2409 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2411 char basename[MAX_QPATH];
2413 Image_StripImageExtension(name, basename, sizeof(basename));
2415 if( last == NULL ) {
2417 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2418 item = r_skinframe.hash[hashindex];
2423 // linearly search through the hash bucket
2424 for( ; item ; item = item->next ) {
2425 if( !strcmp( item->basename, basename ) ) {
2432 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2436 char basename[MAX_QPATH];
2438 Image_StripImageExtension(name, basename, sizeof(basename));
2440 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2441 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2442 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2446 rtexture_t *dyntexture;
2447 // check whether its a dynamic texture
2448 dyntexture = CL_GetDynTexture( basename );
2449 if (!add && !dyntexture)
2451 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2452 memset(item, 0, sizeof(*item));
2453 strlcpy(item->basename, basename, sizeof(item->basename));
2454 item->base = dyntexture; // either NULL or dyntexture handle
2455 item->textureflags = textureflags;
2456 item->comparewidth = comparewidth;
2457 item->compareheight = compareheight;
2458 item->comparecrc = comparecrc;
2459 item->next = r_skinframe.hash[hashindex];
2460 r_skinframe.hash[hashindex] = item;
2462 else if( item->base == NULL )
2464 rtexture_t *dyntexture;
2465 // check whether its a dynamic texture
2466 // 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]
2467 dyntexture = CL_GetDynTexture( basename );
2468 item->base = dyntexture; // either NULL or dyntexture handle
2471 R_SkinFrame_MarkUsed(item);
2475 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2477 unsigned long long avgcolor[5], wsum; \
2485 for(pix = 0; pix < cnt; ++pix) \
2488 for(comp = 0; comp < 3; ++comp) \
2490 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2493 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2495 for(comp = 0; comp < 3; ++comp) \
2496 avgcolor[comp] += getpixel * w; \
2499 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2500 avgcolor[4] += getpixel; \
2502 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2504 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2505 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2506 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2507 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2510 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2512 // FIXME: it should be possible to disable loading various layers using
2513 // cvars, to prevent wasted loading time and memory usage if the user does
2515 qboolean loadnormalmap = true;
2516 qboolean loadgloss = true;
2517 qboolean loadpantsandshirt = true;
2518 qboolean loadglow = true;
2520 unsigned char *pixels;
2521 unsigned char *bumppixels;
2522 unsigned char *basepixels = NULL;
2523 int basepixels_width;
2524 int basepixels_height;
2525 skinframe_t *skinframe;
2530 if (cls.state == ca_dedicated)
2533 // return an existing skinframe if already loaded
2534 // if loading of the first image fails, don't make a new skinframe as it
2535 // would cause all future lookups of this to be missing
2536 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2537 if (skinframe && skinframe->base)
2540 basepixels = loadimagepixelsbgra(name, complain, true);
2541 if (basepixels == NULL)
2544 if (developer_loading.integer)
2545 Con_Printf("loading skin \"%s\"\n", name);
2547 // we've got some pixels to store, so really allocate this new texture now
2549 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2550 skinframe->stain = NULL;
2551 skinframe->merged = NULL;
2552 skinframe->base = r_texture_notexture;
2553 skinframe->pants = NULL;
2554 skinframe->shirt = NULL;
2555 skinframe->nmap = r_texture_blanknormalmap;
2556 skinframe->gloss = NULL;
2557 skinframe->glow = NULL;
2558 skinframe->fog = NULL;
2560 basepixels_width = image_width;
2561 basepixels_height = image_height;
2562 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);
2564 if (textureflags & TEXF_ALPHA)
2566 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2567 if (basepixels[j] < 255)
2569 if (j < basepixels_width * basepixels_height * 4)
2571 // has transparent pixels
2574 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2575 for (j = 0;j < image_width * image_height * 4;j += 4)
2580 pixels[j+3] = basepixels[j+3];
2582 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);
2587 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2588 //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]);
2590 // _norm is the name used by tenebrae and has been adopted as standard
2593 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2595 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);
2599 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2601 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2602 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2603 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);
2605 Mem_Free(bumppixels);
2607 else if (r_shadow_bumpscale_basetexture.value > 0)
2609 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2610 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2611 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);
2615 // _luma is supported for tenebrae compatibility
2616 // (I think it's a very stupid name, but oh well)
2617 // _glow is the preferred name
2618 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;}
2619 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;}
2620 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;}
2621 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;}
2624 Mem_Free(basepixels);
2629 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2631 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL);
2634 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)
2639 for (i = 0;i < width*height;i++)
2640 if (((unsigned char *)&palette[in[i]])[3] > 0)
2642 if (i == width*height)
2645 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2648 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2649 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2652 unsigned char *temp1, *temp2;
2653 skinframe_t *skinframe;
2655 if (cls.state == ca_dedicated)
2658 // if already loaded just return it, otherwise make a new skinframe
2659 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2660 if (skinframe && skinframe->base)
2663 skinframe->stain = NULL;
2664 skinframe->merged = NULL;
2665 skinframe->base = r_texture_notexture;
2666 skinframe->pants = NULL;
2667 skinframe->shirt = NULL;
2668 skinframe->nmap = r_texture_blanknormalmap;
2669 skinframe->gloss = NULL;
2670 skinframe->glow = NULL;
2671 skinframe->fog = NULL;
2673 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2677 if (developer_loading.integer)
2678 Con_Printf("loading 32bit skin \"%s\"\n", name);
2680 if (r_shadow_bumpscale_basetexture.value > 0)
2682 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2683 temp2 = temp1 + width * height * 4;
2684 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2685 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2688 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2689 if (textureflags & TEXF_ALPHA)
2691 for (i = 3;i < width * height * 4;i += 4)
2692 if (skindata[i] < 255)
2694 if (i < width * height * 4)
2696 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2697 memcpy(fogpixels, skindata, width * height * 4);
2698 for (i = 0;i < width * height * 4;i += 4)
2699 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2700 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2701 Mem_Free(fogpixels);
2705 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2706 //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]);
2711 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2714 unsigned char *temp1, *temp2;
2715 unsigned int *palette;
2716 skinframe_t *skinframe;
2718 if (cls.state == ca_dedicated)
2721 // if already loaded just return it, otherwise make a new skinframe
2722 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2723 if (skinframe && skinframe->base)
2726 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2728 skinframe->stain = NULL;
2729 skinframe->merged = NULL;
2730 skinframe->base = r_texture_notexture;
2731 skinframe->pants = NULL;
2732 skinframe->shirt = NULL;
2733 skinframe->nmap = r_texture_blanknormalmap;
2734 skinframe->gloss = NULL;
2735 skinframe->glow = NULL;
2736 skinframe->fog = NULL;
2738 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2742 if (developer_loading.integer)
2743 Con_Printf("loading quake skin \"%s\"\n", name);
2745 if (r_shadow_bumpscale_basetexture.value > 0)
2747 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2748 temp2 = temp1 + width * height * 4;
2749 // use either a custom palette or the quake palette
2750 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2751 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2752 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2755 // use either a custom palette, or the quake palette
2756 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2757 if (loadglowtexture)
2758 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2759 if (loadpantsandshirt)
2761 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2762 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2764 if (skinframe->pants || skinframe->shirt)
2765 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
2766 if (textureflags & TEXF_ALPHA)
2768 for (i = 0;i < width * height;i++)
2769 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2771 if (i < width * height)
2772 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2775 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2776 //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]);
2781 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)
2784 skinframe_t *skinframe;
2786 if (cls.state == ca_dedicated)
2789 // if already loaded just return it, otherwise make a new skinframe
2790 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2791 if (skinframe && skinframe->base)
2794 skinframe->stain = NULL;
2795 skinframe->merged = NULL;
2796 skinframe->base = r_texture_notexture;
2797 skinframe->pants = NULL;
2798 skinframe->shirt = NULL;
2799 skinframe->nmap = r_texture_blanknormalmap;
2800 skinframe->gloss = NULL;
2801 skinframe->glow = NULL;
2802 skinframe->fog = NULL;
2804 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2808 if (developer_loading.integer)
2809 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
2811 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, skinframe->basename, palette, skinframe->textureflags, true);
2812 if (textureflags & TEXF_ALPHA)
2814 for (i = 0;i < width * height;i++)
2815 if (((unsigned char *)alphapalette)[skindata[i]*4+3] < 255)
2817 if (i < width * height)
2818 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), alphapalette, skinframe->textureflags, true); // fog mask
2821 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2822 //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]);
2827 skinframe_t *R_SkinFrame_LoadMissing(void)
2829 skinframe_t *skinframe;
2831 if (cls.state == ca_dedicated)
2834 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2835 skinframe->stain = NULL;
2836 skinframe->merged = NULL;
2837 skinframe->base = r_texture_notexture;
2838 skinframe->pants = NULL;
2839 skinframe->shirt = NULL;
2840 skinframe->nmap = r_texture_blanknormalmap;
2841 skinframe->gloss = NULL;
2842 skinframe->glow = NULL;
2843 skinframe->fog = NULL;
2845 skinframe->avgcolor[0] = rand() / RAND_MAX;
2846 skinframe->avgcolor[1] = rand() / RAND_MAX;
2847 skinframe->avgcolor[2] = rand() / RAND_MAX;
2848 skinframe->avgcolor[3] = 1;
2853 void gl_main_start(void)
2857 memset(r_queries, 0, sizeof(r_queries));
2859 r_qwskincache = NULL;
2860 r_qwskincache_size = 0;
2862 // set up r_skinframe loading system for textures
2863 memset(&r_skinframe, 0, sizeof(r_skinframe));
2864 r_skinframe.loadsequence = 1;
2865 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2867 r_main_texturepool = R_AllocTexturePool();
2868 R_BuildBlankTextures();
2870 if (gl_texturecubemap)
2873 R_BuildNormalizationCube();
2875 r_texture_fogattenuation = NULL;
2876 r_texture_gammaramps = NULL;
2877 //r_texture_fogintensity = NULL;
2878 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2879 memset(&r_waterstate, 0, sizeof(r_waterstate));
2880 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2881 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2882 memset(&r_svbsp, 0, sizeof (r_svbsp));
2884 r_refdef.fogmasktable_density = 0;
2887 extern rtexture_t *loadingscreentexture;
2888 void gl_main_shutdown(void)
2891 qglDeleteQueriesARB(r_maxqueries, r_queries);
2895 memset(r_queries, 0, sizeof(r_queries));
2897 r_qwskincache = NULL;
2898 r_qwskincache_size = 0;
2900 // clear out the r_skinframe state
2901 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2902 memset(&r_skinframe, 0, sizeof(r_skinframe));
2905 Mem_Free(r_svbsp.nodes);
2906 memset(&r_svbsp, 0, sizeof (r_svbsp));
2907 R_FreeTexturePool(&r_main_texturepool);
2908 loadingscreentexture = NULL;
2909 r_texture_blanknormalmap = NULL;
2910 r_texture_white = NULL;
2911 r_texture_grey128 = NULL;
2912 r_texture_black = NULL;
2913 r_texture_whitecube = NULL;
2914 r_texture_normalizationcube = NULL;
2915 r_texture_fogattenuation = NULL;
2916 r_texture_gammaramps = NULL;
2917 //r_texture_fogintensity = NULL;
2918 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2919 memset(&r_waterstate, 0, sizeof(r_waterstate));
2923 extern void CL_ParseEntityLump(char *entitystring);
2924 void gl_main_newmap(void)
2926 // FIXME: move this code to client
2928 char *entities, entname[MAX_QPATH];
2930 Mem_Free(r_qwskincache);
2931 r_qwskincache = NULL;
2932 r_qwskincache_size = 0;
2935 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2936 l = (int)strlen(entname) - 4;
2937 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2939 memcpy(entname + l, ".ent", 5);
2940 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2942 CL_ParseEntityLump(entities);
2947 if (cl.worldmodel->brush.entities)
2948 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2952 void GL_Main_Init(void)
2954 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2956 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2957 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2958 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2959 if (gamemode == GAME_NEHAHRA)
2961 Cvar_RegisterVariable (&gl_fogenable);
2962 Cvar_RegisterVariable (&gl_fogdensity);
2963 Cvar_RegisterVariable (&gl_fogred);
2964 Cvar_RegisterVariable (&gl_foggreen);
2965 Cvar_RegisterVariable (&gl_fogblue);
2966 Cvar_RegisterVariable (&gl_fogstart);
2967 Cvar_RegisterVariable (&gl_fogend);
2968 Cvar_RegisterVariable (&gl_skyclip);
2970 Cvar_RegisterVariable(&r_motionblur);
2971 Cvar_RegisterVariable(&r_motionblur_maxblur);
2972 Cvar_RegisterVariable(&r_motionblur_bmin);
2973 Cvar_RegisterVariable(&r_motionblur_vmin);
2974 Cvar_RegisterVariable(&r_motionblur_vmax);
2975 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2976 Cvar_RegisterVariable(&r_motionblur_randomize);
2977 Cvar_RegisterVariable(&r_damageblur);
2978 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
2979 Cvar_RegisterVariable(&r_equalize_entities_minambient);
2980 Cvar_RegisterVariable(&r_equalize_entities_by);
2981 Cvar_RegisterVariable(&r_equalize_entities_to);
2982 Cvar_RegisterVariable(&r_animcache);
2983 Cvar_RegisterVariable(&r_depthfirst);
2984 Cvar_RegisterVariable(&r_useinfinitefarclip);
2985 Cvar_RegisterVariable(&r_nearclip);
2986 Cvar_RegisterVariable(&r_showbboxes);
2987 Cvar_RegisterVariable(&r_showsurfaces);
2988 Cvar_RegisterVariable(&r_showtris);
2989 Cvar_RegisterVariable(&r_shownormals);
2990 Cvar_RegisterVariable(&r_showlighting);
2991 Cvar_RegisterVariable(&r_showshadowvolumes);
2992 Cvar_RegisterVariable(&r_showcollisionbrushes);
2993 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2994 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2995 Cvar_RegisterVariable(&r_showdisabledepthtest);
2996 Cvar_RegisterVariable(&r_drawportals);
2997 Cvar_RegisterVariable(&r_drawentities);
2998 Cvar_RegisterVariable(&r_cullentities_trace);
2999 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3000 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3001 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3002 Cvar_RegisterVariable(&r_drawviewmodel);
3003 Cvar_RegisterVariable(&r_speeds);
3004 Cvar_RegisterVariable(&r_fullbrights);
3005 Cvar_RegisterVariable(&r_wateralpha);
3006 Cvar_RegisterVariable(&r_dynamic);
3007 Cvar_RegisterVariable(&r_fullbright);
3008 Cvar_RegisterVariable(&r_shadows);
3009 Cvar_RegisterVariable(&r_shadows_darken);
3010 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3011 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3012 Cvar_RegisterVariable(&r_shadows_throwdistance);
3013 Cvar_RegisterVariable(&r_shadows_throwdirection);
3014 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3015 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3016 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3017 Cvar_RegisterVariable(&r_fog_exp2);
3018 Cvar_RegisterVariable(&r_drawfog);
3019 Cvar_RegisterVariable(&r_textureunits);
3020 Cvar_RegisterVariable(&r_glsl);
3021 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3022 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3023 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3024 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3025 Cvar_RegisterVariable(&r_glsl_postprocess);
3026 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3027 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3028 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3029 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3030 Cvar_RegisterVariable(&r_glsl_usegeneric);
3031 Cvar_RegisterVariable(&r_water);
3032 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3033 Cvar_RegisterVariable(&r_water_clippingplanebias);
3034 Cvar_RegisterVariable(&r_water_refractdistort);
3035 Cvar_RegisterVariable(&r_water_reflectdistort);
3036 Cvar_RegisterVariable(&r_lerpsprites);
3037 Cvar_RegisterVariable(&r_lerpmodels);
3038 Cvar_RegisterVariable(&r_lerplightstyles);
3039 Cvar_RegisterVariable(&r_waterscroll);
3040 Cvar_RegisterVariable(&r_bloom);
3041 Cvar_RegisterVariable(&r_bloom_colorscale);
3042 Cvar_RegisterVariable(&r_bloom_brighten);
3043 Cvar_RegisterVariable(&r_bloom_blur);
3044 Cvar_RegisterVariable(&r_bloom_resolution);
3045 Cvar_RegisterVariable(&r_bloom_colorexponent);
3046 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3047 Cvar_RegisterVariable(&r_hdr);
3048 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3049 Cvar_RegisterVariable(&r_hdr_glowintensity);
3050 Cvar_RegisterVariable(&r_hdr_range);
3051 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3052 Cvar_RegisterVariable(&developer_texturelogging);
3053 Cvar_RegisterVariable(&gl_lightmaps);
3054 Cvar_RegisterVariable(&r_test);
3055 Cvar_RegisterVariable(&r_batchmode);
3056 Cvar_RegisterVariable(&r_glsl_saturation);
3057 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3058 Cvar_SetValue("r_fullbrights", 0);
3059 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3061 Cvar_RegisterVariable(&r_track_sprites);
3062 Cvar_RegisterVariable(&r_track_sprites_flags);
3063 Cvar_RegisterVariable(&r_track_sprites_scalew);
3064 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3067 extern void R_Textures_Init(void);
3068 extern void GL_Draw_Init(void);
3069 extern void GL_Main_Init(void);
3070 extern void R_Shadow_Init(void);
3071 extern void R_Sky_Init(void);
3072 extern void GL_Surf_Init(void);
3073 extern void R_Particles_Init(void);
3074 extern void R_Explosion_Init(void);
3075 extern void gl_backend_init(void);
3076 extern void Sbar_Init(void);
3077 extern void R_LightningBeams_Init(void);
3078 extern void Mod_RenderInit(void);
3080 void Render_Init(void)
3092 R_LightningBeams_Init();
3101 extern char *ENGINE_EXTENSIONS;
3104 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3105 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3106 gl_version = (const char *)qglGetString(GL_VERSION);
3107 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3111 if (!gl_platformextensions)
3112 gl_platformextensions = "";
3114 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3115 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3116 Con_Printf("GL_VERSION: %s\n", gl_version);
3117 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3118 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3120 VID_CheckExtensions();
3122 // LordHavoc: report supported extensions
3123 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3125 // clear to black (loading plaque will be seen over this)
3127 qglClearColor(0,0,0,1);CHECKGLERROR
3128 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3131 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3135 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3137 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3140 p = r_refdef.view.frustum + i;
3145 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3149 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3153 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3157 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3161 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3165 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3169 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3173 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3181 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3185 for (i = 0;i < numplanes;i++)
3192 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3196 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3200 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3204 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3208 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3212 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3216 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3220 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3228 //==================================================================================
3230 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3233 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3234 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3235 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3238 typedef struct r_animcache_entity_s
3245 qboolean wantnormals;
3246 qboolean wanttangents;
3248 r_animcache_entity_t;
3250 typedef struct r_animcache_s
3252 r_animcache_entity_t entity[MAX_EDICTS*2];
3258 static r_animcache_t r_animcachestate;
3260 void R_AnimCache_Free(void)
3263 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3265 r_animcachestate.entity[idx].maxvertices = 0;
3266 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3267 r_animcachestate.entity[idx].vertex3f = NULL;
3268 r_animcachestate.entity[idx].normal3f = NULL;
3269 r_animcachestate.entity[idx].svector3f = NULL;
3270 r_animcachestate.entity[idx].tvector3f = NULL;
3272 r_animcachestate.currentindex = 0;
3273 r_animcachestate.maxindex = 0;
3276 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3280 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3282 if (cache->maxvertices >= numvertices)
3285 // Release existing memory
3286 if (cache->vertex3f)
3287 Mem_Free(cache->vertex3f);
3289 // Pad by 1024 verts
3290 cache->maxvertices = (numvertices + 1023) & ~1023;
3291 arraySize = cache->maxvertices * 3;
3293 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3294 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3295 r_animcachestate.entity[cacheIdx].vertex3f = base;
3296 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3297 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3298 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3300 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3303 void R_AnimCache_NewFrame(void)
3307 if (r_animcache.integer && r_drawentities.integer)
3308 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3309 else if (r_animcachestate.maxindex)
3312 r_animcachestate.currentindex = 0;
3314 for (i = 0;i < r_refdef.scene.numentities;i++)
3315 r_refdef.scene.entities[i]->animcacheindex = -1;
3318 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3320 dp_model_t *model = ent->model;
3321 r_animcache_entity_t *c;
3322 // see if it's already cached this frame
3323 if (ent->animcacheindex >= 0)
3325 // add normals/tangents if needed
3326 c = r_animcachestate.entity + ent->animcacheindex;
3328 wantnormals = false;
3329 if (c->wanttangents)
3330 wanttangents = false;
3331 if (wantnormals || wanttangents)
3332 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3336 // see if this ent is worth caching
3337 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3339 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3341 // assign it a cache entry and make sure the arrays are big enough
3342 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3343 ent->animcacheindex = r_animcachestate.currentindex++;
3344 c = r_animcachestate.entity + ent->animcacheindex;
3345 c->wantnormals = wantnormals;
3346 c->wanttangents = wanttangents;
3347 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3352 void R_AnimCache_CacheVisibleEntities(void)
3355 qboolean wantnormals;
3356 qboolean wanttangents;
3358 if (!r_animcachestate.maxindex)
3361 wantnormals = !r_showsurfaces.integer;
3362 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3364 // TODO: thread this?
3366 for (i = 0;i < r_refdef.scene.numentities;i++)
3368 if (!r_refdef.viewcache.entityvisible[i])
3370 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3374 //==================================================================================
3376 static void R_View_UpdateEntityLighting (void)
3379 entity_render_t *ent;
3380 vec3_t tempdiffusenormal, avg;
3381 vec_t f, fa, fd, fdd;
3383 for (i = 0;i < r_refdef.scene.numentities;i++)
3385 ent = r_refdef.scene.entities[i];
3387 // skip unseen models
3388 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3392 if (ent->model && ent->model->brush.num_leafs)
3394 // TODO: use modellight for r_ambient settings on world?
3395 VectorSet(ent->modellight_ambient, 0, 0, 0);
3396 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3397 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3401 // fetch the lighting from the worldmodel data
3402 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));
3403 VectorClear(ent->modellight_diffuse);
3404 VectorClear(tempdiffusenormal);
3405 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3408 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3409 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3410 if(ent->flags & RENDER_EQUALIZE)
3412 // first fix up ambient lighting...
3413 if(r_equalize_entities_minambient.value > 0)
3415 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3418 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3419 if(fa < r_equalize_entities_minambient.value * fd)
3422 // fa'/fd' = minambient
3423 // fa'+0.25*fd' = fa+0.25*fd
3425 // fa' = fd' * minambient
3426 // fd'*(0.25+minambient) = fa+0.25*fd
3428 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3429 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3431 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3432 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
3433 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3434 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3439 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3441 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3442 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3445 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3446 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3447 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3453 VectorSet(ent->modellight_ambient, 1, 1, 1);
3455 // move the light direction into modelspace coordinates for lighting code
3456 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3457 if(VectorLength2(ent->modellight_lightdir) == 0)
3458 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3459 VectorNormalize(ent->modellight_lightdir);
3463 #define MAX_LINEOFSIGHTTRACES 64
3465 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3468 vec3_t boxmins, boxmaxs;
3471 dp_model_t *model = r_refdef.scene.worldmodel;
3473 if (!model || !model->brush.TraceLineOfSight)
3476 // expand the box a little
3477 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3478 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3479 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3480 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3481 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3482 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3485 VectorCopy(eye, start);
3486 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3487 if (model->brush.TraceLineOfSight(model, start, end))
3490 // try various random positions
3491 for (i = 0;i < numsamples;i++)
3493 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3494 if (model->brush.TraceLineOfSight(model, start, end))
3502 static void R_View_UpdateEntityVisible (void)
3505 entity_render_t *ent;
3507 if (!r_drawentities.integer)
3510 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3511 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3513 // worldmodel can check visibility
3514 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3515 for (i = 0;i < r_refdef.scene.numentities;i++)
3517 ent = r_refdef.scene.entities[i];
3518 if (!(ent->flags & renderimask))
3519 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)))
3520 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))
3521 r_refdef.viewcache.entityvisible[i] = true;
3523 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3525 for (i = 0;i < r_refdef.scene.numentities;i++)
3527 ent = r_refdef.scene.entities[i];
3528 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3530 if(R_CanSeeBox(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3531 ent->last_trace_visibility = realtime;
3532 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3533 r_refdef.viewcache.entityvisible[i] = 0;
3540 // no worldmodel or it can't check visibility
3541 for (i = 0;i < r_refdef.scene.numentities;i++)
3543 ent = r_refdef.scene.entities[i];
3544 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));
3549 /// only used if skyrendermasked, and normally returns false
3550 int R_DrawBrushModelsSky (void)
3553 entity_render_t *ent;
3555 if (!r_drawentities.integer)
3559 for (i = 0;i < r_refdef.scene.numentities;i++)
3561 if (!r_refdef.viewcache.entityvisible[i])
3563 ent = r_refdef.scene.entities[i];
3564 if (!ent->model || !ent->model->DrawSky)
3566 ent->model->DrawSky(ent);
3572 static void R_DrawNoModel(entity_render_t *ent);
3573 static void R_DrawModels(void)
3576 entity_render_t *ent;
3578 if (!r_drawentities.integer)
3581 for (i = 0;i < r_refdef.scene.numentities;i++)
3583 if (!r_refdef.viewcache.entityvisible[i])
3585 ent = r_refdef.scene.entities[i];
3586 r_refdef.stats.entities++;
3587 if (ent->model && ent->model->Draw != NULL)
3588 ent->model->Draw(ent);
3594 static void R_DrawModelsDepth(void)
3597 entity_render_t *ent;
3599 if (!r_drawentities.integer)
3602 for (i = 0;i < r_refdef.scene.numentities;i++)
3604 if (!r_refdef.viewcache.entityvisible[i])
3606 ent = r_refdef.scene.entities[i];
3607 if (ent->model && ent->model->DrawDepth != NULL)
3608 ent->model->DrawDepth(ent);
3612 static void R_DrawModelsDebug(void)
3615 entity_render_t *ent;
3617 if (!r_drawentities.integer)
3620 for (i = 0;i < r_refdef.scene.numentities;i++)
3622 if (!r_refdef.viewcache.entityvisible[i])
3624 ent = r_refdef.scene.entities[i];
3625 if (ent->model && ent->model->DrawDebug != NULL)
3626 ent->model->DrawDebug(ent);
3630 static void R_DrawModelsAddWaterPlanes(void)
3633 entity_render_t *ent;
3635 if (!r_drawentities.integer)
3638 for (i = 0;i < r_refdef.scene.numentities;i++)
3640 if (!r_refdef.viewcache.entityvisible[i])
3642 ent = r_refdef.scene.entities[i];
3643 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3644 ent->model->DrawAddWaterPlanes(ent);
3648 static void R_View_SetFrustum(void)
3651 double slopex, slopey;
3652 vec3_t forward, left, up, origin;
3654 // we can't trust r_refdef.view.forward and friends in reflected scenes
3655 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3658 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3659 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3660 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3661 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3662 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3663 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3664 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3665 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3666 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3667 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3668 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3669 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3673 zNear = r_refdef.nearclip;
3674 nudge = 1.0 - 1.0 / (1<<23);
3675 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3676 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3677 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3678 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3679 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3680 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3681 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3682 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3688 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3689 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3690 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3691 r_refdef.view.frustum[0].dist = m[15] - m[12];
3693 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3694 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3695 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3696 r_refdef.view.frustum[1].dist = m[15] + m[12];
3698 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3699 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3700 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3701 r_refdef.view.frustum[2].dist = m[15] - m[13];
3703 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3704 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3705 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3706 r_refdef.view.frustum[3].dist = m[15] + m[13];
3708 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3709 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3710 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3711 r_refdef.view.frustum[4].dist = m[15] - m[14];
3713 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3714 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3715 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3716 r_refdef.view.frustum[5].dist = m[15] + m[14];
3719 if (r_refdef.view.useperspective)
3721 slopex = 1.0 / r_refdef.view.frustum_x;
3722 slopey = 1.0 / r_refdef.view.frustum_y;
3723 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3724 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3725 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3726 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3727 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3729 // Leaving those out was a mistake, those were in the old code, and they
3730 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3731 // I couldn't reproduce it after adding those normalizations. --blub
3732 VectorNormalize(r_refdef.view.frustum[0].normal);
3733 VectorNormalize(r_refdef.view.frustum[1].normal);
3734 VectorNormalize(r_refdef.view.frustum[2].normal);
3735 VectorNormalize(r_refdef.view.frustum[3].normal);
3737 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3738 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]);
3739 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]);
3740 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]);
3741 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]);
3743 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3744 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3745 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3746 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3747 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3751 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3752 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3753 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3754 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3755 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3756 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3757 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3758 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3759 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3760 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3762 r_refdef.view.numfrustumplanes = 5;
3764 if (r_refdef.view.useclipplane)
3766 r_refdef.view.numfrustumplanes = 6;
3767 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3770 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3771 PlaneClassify(r_refdef.view.frustum + i);
3773 // LordHavoc: note to all quake engine coders, Quake had a special case
3774 // for 90 degrees which assumed a square view (wrong), so I removed it,
3775 // Quake2 has it disabled as well.
3777 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3778 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3779 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3780 //PlaneClassify(&frustum[0]);
3782 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3783 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3784 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3785 //PlaneClassify(&frustum[1]);
3787 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3788 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3789 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3790 //PlaneClassify(&frustum[2]);
3792 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3793 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3794 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3795 //PlaneClassify(&frustum[3]);
3798 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3799 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3800 //PlaneClassify(&frustum[4]);
3803 void R_View_Update(void)
3805 R_View_SetFrustum();
3806 R_View_WorldVisibility(r_refdef.view.useclipplane);
3807 R_View_UpdateEntityVisible();
3808 R_View_UpdateEntityLighting();
3811 void R_SetupView(qboolean allowwaterclippingplane)
3813 const double *customclipplane = NULL;
3815 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3817 // LordHavoc: couldn't figure out how to make this approach the
3818 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3819 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3820 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3821 dist = r_refdef.view.clipplane.dist;
3822 plane[0] = r_refdef.view.clipplane.normal[0];
3823 plane[1] = r_refdef.view.clipplane.normal[1];
3824 plane[2] = r_refdef.view.clipplane.normal[2];
3826 customclipplane = plane;
3829 if (!r_refdef.view.useperspective)
3830 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);
3831 else if (gl_stencil && r_useinfinitefarclip.integer)
3832 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);
3834 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);
3835 R_SetViewport(&r_refdef.view.viewport);
3838 void R_ResetViewRendering2D(void)
3840 r_viewport_t viewport;
3843 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3844 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);
3845 R_SetViewport(&viewport);
3846 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3847 GL_Color(1, 1, 1, 1);
3848 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3849 GL_BlendFunc(GL_ONE, GL_ZERO);
3850 GL_AlphaTest(false);
3851 GL_ScissorTest(false);
3852 GL_DepthMask(false);
3853 GL_DepthRange(0, 1);
3854 GL_DepthTest(false);
3855 R_Mesh_Matrix(&identitymatrix);
3856 R_Mesh_ResetTextureState();
3857 GL_PolygonOffset(0, 0);
3858 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3859 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3860 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3861 qglStencilMask(~0);CHECKGLERROR
3862 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3863 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3864 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3865 R_SetupGenericShader(true);
3868 void R_ResetViewRendering3D(void)
3873 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3874 GL_Color(1, 1, 1, 1);
3875 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3876 GL_BlendFunc(GL_ONE, GL_ZERO);
3877 GL_AlphaTest(false);
3878 GL_ScissorTest(true);
3880 GL_DepthRange(0, 1);
3882 R_Mesh_Matrix(&identitymatrix);
3883 R_Mesh_ResetTextureState();
3884 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3885 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3886 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3887 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3888 qglStencilMask(~0);CHECKGLERROR
3889 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3890 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3891 GL_CullFace(r_refdef.view.cullface_back);
3892 R_SetupGenericShader(true);
3895 void R_RenderScene(void);
3896 void R_RenderWaterPlanes(void);
3898 static void R_Water_StartFrame(void)
3901 int waterwidth, waterheight, texturewidth, textureheight;
3902 r_waterstate_waterplane_t *p;
3904 // set waterwidth and waterheight to the water resolution that will be
3905 // used (often less than the screen resolution for faster rendering)
3906 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3907 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3909 // calculate desired texture sizes
3910 // can't use water if the card does not support the texture size
3911 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3912 texturewidth = textureheight = waterwidth = waterheight = 0;
3913 else if (gl_support_arb_texture_non_power_of_two)
3915 texturewidth = waterwidth;
3916 textureheight = waterheight;
3920 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3921 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3924 // allocate textures as needed
3925 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3927 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3928 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3930 if (p->texture_refraction)
3931 R_FreeTexture(p->texture_refraction);
3932 p->texture_refraction = NULL;
3933 if (p->texture_reflection)
3934 R_FreeTexture(p->texture_reflection);
3935 p->texture_reflection = NULL;
3937 memset(&r_waterstate, 0, sizeof(r_waterstate));
3938 r_waterstate.texturewidth = texturewidth;
3939 r_waterstate.textureheight = textureheight;
3942 if (r_waterstate.texturewidth)
3944 r_waterstate.enabled = true;
3946 // when doing a reduced render (HDR) we want to use a smaller area
3947 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3948 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3950 // set up variables that will be used in shader setup
3951 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3952 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3953 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3954 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3957 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3958 r_waterstate.numwaterplanes = 0;
3961 void R_Water_AddWaterPlane(msurface_t *surface)
3963 int triangleindex, planeindex;
3969 r_waterstate_waterplane_t *p;
3970 texture_t *t = R_GetCurrentTexture(surface->texture);
3971 // just use the first triangle with a valid normal for any decisions
3972 VectorClear(normal);
3973 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3975 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3976 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3977 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3978 TriangleNormal(vert[0], vert[1], vert[2], normal);
3979 if (VectorLength2(normal) >= 0.001)
3983 VectorCopy(normal, plane.normal);
3984 VectorNormalize(plane.normal);
3985 plane.dist = DotProduct(vert[0], plane.normal);
3986 PlaneClassify(&plane);
3987 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3989 // skip backfaces (except if nocullface is set)
3990 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3992 VectorNegate(plane.normal, plane.normal);
3994 PlaneClassify(&plane);
3998 // find a matching plane if there is one
3999 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4000 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4002 if (planeindex >= r_waterstate.maxwaterplanes)
4003 return; // nothing we can do, out of planes
4005 // if this triangle does not fit any known plane rendered this frame, add one
4006 if (planeindex >= r_waterstate.numwaterplanes)
4008 // store the new plane
4009 r_waterstate.numwaterplanes++;
4011 // clear materialflags and pvs
4012 p->materialflags = 0;
4013 p->pvsvalid = false;
4015 // merge this surface's materialflags into the waterplane
4016 p->materialflags |= t->currentmaterialflags;
4017 // merge this surface's PVS into the waterplane
4018 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4019 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4020 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4022 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4027 static void R_Water_ProcessPlanes(void)
4029 r_refdef_view_t originalview;
4030 r_refdef_view_t myview;
4032 r_waterstate_waterplane_t *p;
4034 originalview = r_refdef.view;
4036 // make sure enough textures are allocated
4037 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4039 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4041 if (!p->texture_refraction)
4042 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);
4043 if (!p->texture_refraction)
4047 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4049 if (!p->texture_reflection)
4050 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);
4051 if (!p->texture_reflection)
4057 r_refdef.view = originalview;
4058 r_refdef.view.showdebug = false;
4059 r_refdef.view.width = r_waterstate.waterwidth;
4060 r_refdef.view.height = r_waterstate.waterheight;
4061 r_refdef.view.useclipplane = true;
4062 myview = r_refdef.view;
4063 r_waterstate.renderingscene = true;
4064 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4066 // render the normal view scene and copy into texture
4067 // (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)
4068 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4070 r_refdef.view = myview;
4071 r_refdef.view.clipplane = p->plane;
4072 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4073 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4074 PlaneClassify(&r_refdef.view.clipplane);
4076 R_ResetViewRendering3D();
4077 R_ClearScreen(r_refdef.fogenabled);
4081 // copy view into the screen texture
4082 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4083 GL_ActiveTexture(0);
4085 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
4088 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4090 r_refdef.view = myview;
4091 // render reflected scene and copy into texture
4092 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4093 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4094 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4095 r_refdef.view.clipplane = p->plane;
4096 // reverse the cullface settings for this render
4097 r_refdef.view.cullface_front = GL_FRONT;
4098 r_refdef.view.cullface_back = GL_BACK;
4099 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4101 r_refdef.view.usecustompvs = true;
4103 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4105 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4108 R_ResetViewRendering3D();
4109 R_ClearScreen(r_refdef.fogenabled);
4113 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4114 GL_ActiveTexture(0);
4116 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
4119 r_waterstate.renderingscene = false;
4120 r_refdef.view = originalview;
4121 R_ResetViewRendering3D();
4122 R_ClearScreen(r_refdef.fogenabled);
4126 r_refdef.view = originalview;
4127 r_waterstate.renderingscene = false;
4128 Cvar_SetValueQuick(&r_water, 0);
4129 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4133 void R_Bloom_StartFrame(void)
4135 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4137 // set bloomwidth and bloomheight to the bloom resolution that will be
4138 // used (often less than the screen resolution for faster rendering)
4139 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4140 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4141 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4142 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
4143 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
4145 // calculate desired texture sizes
4146 if (gl_support_arb_texture_non_power_of_two)
4148 screentexturewidth = r_refdef.view.width;
4149 screentextureheight = r_refdef.view.height;
4150 bloomtexturewidth = r_bloomstate.bloomwidth;
4151 bloomtextureheight = r_bloomstate.bloomheight;
4155 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4156 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4157 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4158 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4161 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))
4163 Cvar_SetValueQuick(&r_hdr, 0);
4164 Cvar_SetValueQuick(&r_bloom, 0);
4165 Cvar_SetValueQuick(&r_motionblur, 0);
4166 Cvar_SetValueQuick(&r_damageblur, 0);
4169 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)))
4170 screentexturewidth = screentextureheight = 0;
4171 if (!r_hdr.integer && !r_bloom.integer)
4172 bloomtexturewidth = bloomtextureheight = 0;
4174 // allocate textures as needed
4175 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4177 if (r_bloomstate.texture_screen)
4178 R_FreeTexture(r_bloomstate.texture_screen);
4179 r_bloomstate.texture_screen = NULL;
4180 r_bloomstate.screentexturewidth = screentexturewidth;
4181 r_bloomstate.screentextureheight = screentextureheight;
4182 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4183 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);
4185 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4187 if (r_bloomstate.texture_bloom)
4188 R_FreeTexture(r_bloomstate.texture_bloom);
4189 r_bloomstate.texture_bloom = NULL;
4190 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4191 r_bloomstate.bloomtextureheight = bloomtextureheight;
4192 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4193 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);
4196 // when doing a reduced render (HDR) we want to use a smaller area
4197 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4198 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4199 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4200 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4201 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4203 // set up a texcoord array for the full resolution screen image
4204 // (we have to keep this around to copy back during final render)
4205 r_bloomstate.screentexcoord2f[0] = 0;
4206 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4207 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4208 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4209 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4210 r_bloomstate.screentexcoord2f[5] = 0;
4211 r_bloomstate.screentexcoord2f[6] = 0;
4212 r_bloomstate.screentexcoord2f[7] = 0;
4214 // set up a texcoord array for the reduced resolution bloom image
4215 // (which will be additive blended over the screen image)
4216 r_bloomstate.bloomtexcoord2f[0] = 0;
4217 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4218 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4219 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4220 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4221 r_bloomstate.bloomtexcoord2f[5] = 0;
4222 r_bloomstate.bloomtexcoord2f[6] = 0;
4223 r_bloomstate.bloomtexcoord2f[7] = 0;
4225 if (r_hdr.integer || r_bloom.integer)
4227 r_bloomstate.enabled = true;
4228 r_bloomstate.hdr = r_hdr.integer != 0;
4231 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);
4234 void R_Bloom_CopyBloomTexture(float colorscale)
4236 r_refdef.stats.bloom++;
4238 // scale down screen texture to the bloom texture size
4240 R_SetViewport(&r_bloomstate.viewport);
4241 GL_BlendFunc(GL_ONE, GL_ZERO);
4242 GL_Color(colorscale, colorscale, colorscale, 1);
4243 // TODO: optimize with multitexture or GLSL
4244 R_SetupGenericShader(true);
4245 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4246 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4247 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4248 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4250 // we now have a bloom image in the framebuffer
4251 // copy it into the bloom image texture for later processing
4252 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4253 GL_ActiveTexture(0);
4255 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4256 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4259 void R_Bloom_CopyHDRTexture(void)
4261 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4262 GL_ActiveTexture(0);
4264 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
4265 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4268 void R_Bloom_MakeTexture(void)
4271 float xoffset, yoffset, r, brighten;
4273 r_refdef.stats.bloom++;
4275 R_ResetViewRendering2D();
4276 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4277 R_Mesh_ColorPointer(NULL, 0, 0);
4278 R_SetupGenericShader(true);
4280 // we have a bloom image in the framebuffer
4282 R_SetViewport(&r_bloomstate.viewport);
4284 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4287 r = bound(0, r_bloom_colorexponent.value / x, 1);
4288 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4289 GL_Color(r, r, r, 1);
4290 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4291 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4292 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4293 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4295 // copy the vertically blurred bloom view to a texture
4296 GL_ActiveTexture(0);
4298 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4299 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4302 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4303 brighten = r_bloom_brighten.value;
4305 brighten *= r_hdr_range.value;
4306 brighten = sqrt(brighten);
4308 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4309 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4310 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4312 for (dir = 0;dir < 2;dir++)
4314 // blend on at multiple vertical offsets to achieve a vertical blur
4315 // TODO: do offset blends using GLSL
4316 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4317 GL_BlendFunc(GL_ONE, GL_ZERO);
4318 for (x = -range;x <= range;x++)
4320 if (!dir){xoffset = 0;yoffset = x;}
4321 else {xoffset = x;yoffset = 0;}
4322 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4323 yoffset /= (float)r_bloomstate.bloomtextureheight;
4324 // compute a texcoord array with the specified x and y offset
4325 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4326 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4327 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4328 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4329 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4330 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4331 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4332 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4333 // this r value looks like a 'dot' particle, fading sharply to
4334 // black at the edges
4335 // (probably not realistic but looks good enough)
4336 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4337 //r = brighten/(range*2+1);
4338 r = brighten / (range * 2 + 1);
4340 r *= (1 - x*x/(float)(range*range));
4341 GL_Color(r, r, r, 1);
4342 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4343 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4344 GL_BlendFunc(GL_ONE, GL_ONE);
4347 // copy the vertically blurred bloom view to a texture
4348 GL_ActiveTexture(0);
4350 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4351 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4354 // apply subtract last
4355 // (just like it would be in a GLSL shader)
4356 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4358 GL_BlendFunc(GL_ONE, GL_ZERO);
4359 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4360 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4361 GL_Color(1, 1, 1, 1);
4362 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4363 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4365 GL_BlendFunc(GL_ONE, GL_ONE);
4366 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4367 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4368 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4369 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4370 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4371 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4372 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4374 // copy the darkened bloom view to a texture
4375 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4376 GL_ActiveTexture(0);
4378 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4379 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4383 void R_HDR_RenderBloomTexture(void)
4385 int oldwidth, oldheight;
4386 float oldcolorscale;
4388 oldcolorscale = r_refdef.view.colorscale;
4389 oldwidth = r_refdef.view.width;
4390 oldheight = r_refdef.view.height;
4391 r_refdef.view.width = r_bloomstate.bloomwidth;
4392 r_refdef.view.height = r_bloomstate.bloomheight;
4394 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4395 // TODO: add exposure compensation features
4396 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4398 r_refdef.view.showdebug = false;
4399 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4401 R_ResetViewRendering3D();
4403 R_ClearScreen(r_refdef.fogenabled);
4404 if (r_timereport_active)
4405 R_TimeReport("HDRclear");
4408 if (r_timereport_active)
4409 R_TimeReport("visibility");
4411 // only do secondary renders with HDR if r_hdr is 2 or higher
4412 r_waterstate.numwaterplanes = 0;
4413 if (r_waterstate.enabled && r_hdr.integer >= 2)
4414 R_RenderWaterPlanes();
4416 r_refdef.view.showdebug = true;
4418 r_waterstate.numwaterplanes = 0;
4420 R_ResetViewRendering2D();
4422 R_Bloom_CopyHDRTexture();
4423 R_Bloom_MakeTexture();
4425 // restore the view settings
4426 r_refdef.view.width = oldwidth;
4427 r_refdef.view.height = oldheight;
4428 r_refdef.view.colorscale = oldcolorscale;
4430 R_ResetViewRendering3D();
4432 R_ClearScreen(r_refdef.fogenabled);
4433 if (r_timereport_active)
4434 R_TimeReport("viewclear");
4437 static void R_BlendView(void)
4439 if (r_bloomstate.texture_screen)
4441 // make sure the buffer is available
4442 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4444 R_ResetViewRendering2D();
4445 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4446 R_Mesh_ColorPointer(NULL, 0, 0);
4447 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4448 GL_ActiveTexture(0);CHECKGLERROR
4450 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4452 // declare variables
4454 static float avgspeed;
4456 speed = VectorLength(cl.movement_velocity);
4458 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4459 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4461 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4462 speed = bound(0, speed, 1);
4463 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4465 // calculate values into a standard alpha
4466 cl.motionbluralpha = 1 - exp(-
4468 (r_motionblur.value * speed / 80)
4470 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4473 max(0.0001, cl.time - cl.oldtime) // fps independent
4476 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4477 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4479 if (cl.motionbluralpha > 0)
4481 R_SetupGenericShader(true);
4482 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4483 GL_Color(1, 1, 1, cl.motionbluralpha);
4484 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4485 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4486 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4487 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4491 // copy view into the screen texture
4492 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
4493 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4496 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4498 unsigned int permutation =
4499 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4500 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4501 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4502 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4503 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4505 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4507 // render simple bloom effect
4508 // copy the screen and shrink it and darken it for the bloom process
4509 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4510 // make the bloom texture
4511 R_Bloom_MakeTexture();
4514 R_ResetViewRendering2D();
4515 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4516 R_Mesh_ColorPointer(NULL, 0, 0);
4517 GL_Color(1, 1, 1, 1);
4518 GL_BlendFunc(GL_ONE, GL_ZERO);
4519 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4520 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4521 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4522 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4523 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4524 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4525 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4526 if (r_glsl_permutation->loc_TintColor >= 0)
4527 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4528 if (r_glsl_permutation->loc_ClientTime >= 0)
4529 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4530 if (r_glsl_permutation->loc_PixelSize >= 0)
4531 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4532 if (r_glsl_permutation->loc_UserVec1 >= 0)
4534 float a=0, b=0, c=0, d=0;
4535 #if _MSC_VER >= 1400
4536 #define sscanf sscanf_s
4538 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4539 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4541 if (r_glsl_permutation->loc_UserVec2 >= 0)
4543 float a=0, b=0, c=0, d=0;
4544 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4545 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4547 if (r_glsl_permutation->loc_UserVec3 >= 0)
4549 float a=0, b=0, c=0, d=0;
4550 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4551 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4553 if (r_glsl_permutation->loc_UserVec4 >= 0)
4555 float a=0, b=0, c=0, d=0;
4556 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4557 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4559 if (r_glsl_permutation->loc_Saturation >= 0)
4560 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4561 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4562 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4568 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4570 // render high dynamic range bloom effect
4571 // the bloom texture was made earlier this render, so we just need to
4572 // blend it onto the screen...
4573 R_ResetViewRendering2D();
4574 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4575 R_Mesh_ColorPointer(NULL, 0, 0);
4576 R_SetupGenericShader(true);
4577 GL_Color(1, 1, 1, 1);
4578 GL_BlendFunc(GL_ONE, GL_ONE);
4579 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4580 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4581 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4582 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4584 else if (r_bloomstate.texture_bloom)
4586 // render simple bloom effect
4587 // copy the screen and shrink it and darken it for the bloom process
4588 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4589 // make the bloom texture
4590 R_Bloom_MakeTexture();
4591 // put the original screen image back in place and blend the bloom
4593 R_ResetViewRendering2D();
4594 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4595 R_Mesh_ColorPointer(NULL, 0, 0);
4596 GL_Color(1, 1, 1, 1);
4597 GL_BlendFunc(GL_ONE, GL_ZERO);
4598 // do both in one pass if possible
4599 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4600 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4601 if (r_textureunits.integer >= 2 && gl_combine.integer)
4603 R_SetupGenericTwoTextureShader(GL_ADD);
4604 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4605 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4609 R_SetupGenericShader(true);
4610 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4611 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4612 // now blend on the bloom texture
4613 GL_BlendFunc(GL_ONE, GL_ONE);
4614 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4615 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4617 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4618 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4620 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4622 // apply a color tint to the whole view
4623 R_ResetViewRendering2D();
4624 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4625 R_Mesh_ColorPointer(NULL, 0, 0);
4626 R_SetupGenericShader(false);
4627 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4628 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4629 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4633 matrix4x4_t r_waterscrollmatrix;
4635 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4637 if (r_refdef.fog_density)
4639 r_refdef.fogcolor[0] = r_refdef.fog_red;
4640 r_refdef.fogcolor[1] = r_refdef.fog_green;
4641 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4643 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4644 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4645 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4646 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4650 VectorCopy(r_refdef.fogcolor, fogvec);
4651 // color.rgb *= ContrastBoost * SceneBrightness;
4652 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4653 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4654 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4655 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4660 void R_UpdateVariables(void)
4664 r_refdef.scene.ambient = r_ambient.value;
4666 r_refdef.farclip = 4096;
4667 if (r_refdef.scene.worldmodel)
4668 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4669 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4671 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4672 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4673 r_refdef.polygonfactor = 0;
4674 r_refdef.polygonoffset = 0;
4675 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4676 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4678 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4679 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4680 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4681 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4682 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4683 if (r_showsurfaces.integer)
4685 r_refdef.scene.rtworld = false;
4686 r_refdef.scene.rtworldshadows = false;
4687 r_refdef.scene.rtdlight = false;
4688 r_refdef.scene.rtdlightshadows = false;
4689 r_refdef.lightmapintensity = 0;
4692 if (gamemode == GAME_NEHAHRA)
4694 if (gl_fogenable.integer)
4696 r_refdef.oldgl_fogenable = true;
4697 r_refdef.fog_density = gl_fogdensity.value;
4698 r_refdef.fog_red = gl_fogred.value;
4699 r_refdef.fog_green = gl_foggreen.value;
4700 r_refdef.fog_blue = gl_fogblue.value;
4701 r_refdef.fog_alpha = 1;
4702 r_refdef.fog_start = 0;
4703 r_refdef.fog_end = gl_skyclip.value;
4704 r_refdef.fog_height = 1<<30;
4705 r_refdef.fog_fadedepth = 128;
4707 else if (r_refdef.oldgl_fogenable)
4709 r_refdef.oldgl_fogenable = false;
4710 r_refdef.fog_density = 0;
4711 r_refdef.fog_red = 0;
4712 r_refdef.fog_green = 0;
4713 r_refdef.fog_blue = 0;
4714 r_refdef.fog_alpha = 0;
4715 r_refdef.fog_start = 0;
4716 r_refdef.fog_end = 0;
4717 r_refdef.fog_height = 1<<30;
4718 r_refdef.fog_fadedepth = 128;
4722 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4723 r_refdef.fog_start = max(0, r_refdef.fog_start);
4724 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4726 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4728 if (r_refdef.fog_density && r_drawfog.integer)
4730 r_refdef.fogenabled = true;
4731 // this is the point where the fog reaches 0.9986 alpha, which we
4732 // consider a good enough cutoff point for the texture
4733 // (0.9986 * 256 == 255.6)
4734 if (r_fog_exp2.integer)
4735 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4737 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4738 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4739 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4740 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4741 // fog color was already set
4742 // update the fog texture
4743 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)
4744 R_BuildFogTexture();
4747 r_refdef.fogenabled = false;
4749 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4751 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4753 // build GLSL gamma texture
4754 #define RAMPWIDTH 256
4755 unsigned short ramp[RAMPWIDTH * 3];
4756 unsigned char rampbgr[RAMPWIDTH][4];
4759 r_texture_gammaramps_serial = vid_gammatables_serial;
4761 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4762 for(i = 0; i < RAMPWIDTH; ++i)
4764 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4765 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4766 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4769 if (r_texture_gammaramps)
4771 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4775 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);
4781 // remove GLSL gamma texture
4785 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4786 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4792 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4793 if( scenetype != r_currentscenetype ) {
4794 // store the old scenetype
4795 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4796 r_currentscenetype = scenetype;
4797 // move in the new scene
4798 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4807 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4809 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4810 if( scenetype == r_currentscenetype ) {
4811 return &r_refdef.scene;
4813 return &r_scenes_store[ scenetype ];
4822 void R_RenderView(void)
4824 if (r_timereport_active)
4825 R_TimeReport("start");
4826 r_frame++; // used only by R_GetCurrentTexture
4827 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4829 R_AnimCache_NewFrame();
4831 if (r_refdef.view.isoverlay)
4833 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4834 GL_Clear( GL_DEPTH_BUFFER_BIT );
4835 R_TimeReport("depthclear");
4837 r_refdef.view.showdebug = false;
4839 r_waterstate.enabled = false;
4840 r_waterstate.numwaterplanes = 0;
4848 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4849 return; //Host_Error ("R_RenderView: NULL worldmodel");
4851 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4853 // break apart the view matrix into vectors for various purposes
4854 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4855 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4856 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4857 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4858 // make an inverted copy of the view matrix for tracking sprites
4859 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4861 R_Shadow_UpdateWorldLightSelection();
4863 R_Bloom_StartFrame();
4864 R_Water_StartFrame();
4867 if (r_timereport_active)
4868 R_TimeReport("viewsetup");
4870 R_ResetViewRendering3D();
4872 if (r_refdef.view.clear || r_refdef.fogenabled)
4874 R_ClearScreen(r_refdef.fogenabled);
4875 if (r_timereport_active)
4876 R_TimeReport("viewclear");
4878 r_refdef.view.clear = true;
4880 // this produces a bloom texture to be used in R_BlendView() later
4882 R_HDR_RenderBloomTexture();
4884 r_refdef.view.showdebug = true;
4887 if (r_timereport_active)
4888 R_TimeReport("visibility");
4890 r_waterstate.numwaterplanes = 0;
4891 if (r_waterstate.enabled)
4892 R_RenderWaterPlanes();
4895 r_waterstate.numwaterplanes = 0;
4898 if (r_timereport_active)
4899 R_TimeReport("blendview");
4901 GL_Scissor(0, 0, vid.width, vid.height);
4902 GL_ScissorTest(false);
4906 void R_RenderWaterPlanes(void)
4908 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4910 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4911 if (r_timereport_active)
4912 R_TimeReport("waterworld");
4915 // don't let sound skip if going slow
4916 if (r_refdef.scene.extraupdate)
4919 R_DrawModelsAddWaterPlanes();
4920 if (r_timereport_active)
4921 R_TimeReport("watermodels");
4923 if (r_waterstate.numwaterplanes)
4925 R_Water_ProcessPlanes();
4926 if (r_timereport_active)
4927 R_TimeReport("waterscenes");
4931 extern void R_DrawLightningBeams (void);
4932 extern void VM_CL_AddPolygonsToMeshQueue (void);
4933 extern void R_DrawPortals (void);
4934 extern cvar_t cl_locs_show;
4935 static void R_DrawLocs(void);
4936 static void R_DrawEntityBBoxes(void);
4937 void R_RenderScene(void)
4939 r_refdef.stats.renders++;
4943 // don't let sound skip if going slow
4944 if (r_refdef.scene.extraupdate)
4947 R_MeshQueue_BeginScene();
4951 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);
4953 if (cl.csqc_vidvars.drawworld)
4955 // don't let sound skip if going slow
4956 if (r_refdef.scene.extraupdate)
4959 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4961 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4962 if (r_timereport_active)
4963 R_TimeReport("worldsky");
4966 if (R_DrawBrushModelsSky() && r_timereport_active)
4967 R_TimeReport("bmodelsky");
4969 if (skyrendermasked && skyrenderlater)
4971 // we have to force off the water clipping plane while rendering sky
4978 R_AnimCache_CacheVisibleEntities();
4980 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4982 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4983 if (r_timereport_active)
4984 R_TimeReport("worlddepth");
4986 if (r_depthfirst.integer >= 2)
4988 R_DrawModelsDepth();
4989 if (r_timereport_active)
4990 R_TimeReport("modeldepth");
4993 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4995 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4996 if (r_timereport_active)
4997 R_TimeReport("world");
5000 // don't let sound skip if going slow
5001 if (r_refdef.scene.extraupdate)
5005 if (r_timereport_active)
5006 R_TimeReport("models");
5008 // don't let sound skip if going slow
5009 if (r_refdef.scene.extraupdate)
5012 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5014 R_DrawModelShadows();
5015 R_ResetViewRendering3D();
5016 // don't let sound skip if going slow
5017 if (r_refdef.scene.extraupdate)
5021 R_ShadowVolumeLighting(false);
5022 if (r_timereport_active)
5023 R_TimeReport("rtlights");
5025 // don't let sound skip if going slow
5026 if (r_refdef.scene.extraupdate)
5029 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5031 R_DrawModelShadows();
5032 R_ResetViewRendering3D();
5033 // don't let sound skip if going slow
5034 if (r_refdef.scene.extraupdate)
5038 if (cl.csqc_vidvars.drawworld)
5040 R_DrawLightningBeams();
5041 if (r_timereport_active)
5042 R_TimeReport("lightning");
5045 if (r_timereport_active)
5046 R_TimeReport("decals");
5049 if (r_timereport_active)
5050 R_TimeReport("particles");
5053 if (r_timereport_active)
5054 R_TimeReport("explosions");
5057 R_SetupGenericShader(true);
5058 VM_CL_AddPolygonsToMeshQueue();
5060 if (r_refdef.view.showdebug)
5062 if (cl_locs_show.integer)
5065 if (r_timereport_active)
5066 R_TimeReport("showlocs");
5069 if (r_drawportals.integer)
5072 if (r_timereport_active)
5073 R_TimeReport("portals");
5076 if (r_showbboxes.value > 0)
5078 R_DrawEntityBBoxes();
5079 if (r_timereport_active)
5080 R_TimeReport("bboxes");
5084 R_SetupGenericShader(true);
5085 R_MeshQueue_RenderTransparent();
5086 if (r_timereport_active)
5087 R_TimeReport("drawtrans");
5089 R_SetupGenericShader(true);
5091 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))
5093 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5094 if (r_timereport_active)
5095 R_TimeReport("worlddebug");
5096 R_DrawModelsDebug();
5097 if (r_timereport_active)
5098 R_TimeReport("modeldebug");
5101 R_SetupGenericShader(true);
5103 if (cl.csqc_vidvars.drawworld)
5106 if (r_timereport_active)
5107 R_TimeReport("coronas");
5110 // don't let sound skip if going slow
5111 if (r_refdef.scene.extraupdate)
5114 R_ResetViewRendering2D();
5117 static const unsigned short bboxelements[36] =
5127 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5130 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5132 RSurf_ActiveWorldEntity();
5134 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5135 GL_DepthMask(false);
5136 GL_DepthRange(0, 1);
5137 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5138 R_Mesh_ResetTextureState();
5140 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5141 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5142 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5143 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5144 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5145 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5146 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5147 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5148 R_FillColors(color4f, 8, cr, cg, cb, ca);
5149 if (r_refdef.fogenabled)
5151 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5153 f1 = RSurf_FogVertex(v);
5155 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5156 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5157 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5160 R_Mesh_VertexPointer(vertex3f, 0, 0);
5161 R_Mesh_ColorPointer(color4f, 0, 0);
5162 R_Mesh_ResetTextureState();
5163 R_SetupGenericShader(false);
5164 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5167 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5171 prvm_edict_t *edict;
5172 prvm_prog_t *prog_save = prog;
5174 // this function draws bounding boxes of server entities
5178 GL_CullFace(GL_NONE);
5179 R_SetupGenericShader(false);
5183 for (i = 0;i < numsurfaces;i++)
5185 edict = PRVM_EDICT_NUM(surfacelist[i]);
5186 switch ((int)edict->fields.server->solid)
5188 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5189 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5190 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5191 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5192 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5193 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5195 color[3] *= r_showbboxes.value;
5196 color[3] = bound(0, color[3], 1);
5197 GL_DepthTest(!r_showdisabledepthtest.integer);
5198 GL_CullFace(r_refdef.view.cullface_front);
5199 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5205 static void R_DrawEntityBBoxes(void)
5208 prvm_edict_t *edict;
5210 prvm_prog_t *prog_save = prog;
5212 // this function draws bounding boxes of server entities
5218 for (i = 0;i < prog->num_edicts;i++)
5220 edict = PRVM_EDICT_NUM(i);
5221 if (edict->priv.server->free)
5223 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5224 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5226 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5228 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5229 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5235 static const int nomodelelement3i[24] =
5247 static const unsigned short nomodelelement3s[24] =
5259 static const float nomodelvertex3f[6*3] =
5269 static const float nomodelcolor4f[6*4] =
5271 0.0f, 0.0f, 0.5f, 1.0f,
5272 0.0f, 0.0f, 0.5f, 1.0f,
5273 0.0f, 0.5f, 0.0f, 1.0f,
5274 0.0f, 0.5f, 0.0f, 1.0f,
5275 0.5f, 0.0f, 0.0f, 1.0f,
5276 0.5f, 0.0f, 0.0f, 1.0f
5279 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5285 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);
5287 // this is only called once per entity so numsurfaces is always 1, and
5288 // surfacelist is always {0}, so this code does not handle batches
5290 if (rsurface.ent_flags & RENDER_ADDITIVE)
5292 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5293 GL_DepthMask(false);
5295 else if (rsurface.ent_color[3] < 1)
5297 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5298 GL_DepthMask(false);
5302 GL_BlendFunc(GL_ONE, GL_ZERO);
5305 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5306 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5307 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5308 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5309 R_SetupGenericShader(false);
5310 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5311 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5312 R_Mesh_ColorPointer(color4f, 0, 0);
5313 for (i = 0, c = color4f;i < 6;i++, c += 4)
5315 c[0] *= rsurface.ent_color[0];
5316 c[1] *= rsurface.ent_color[1];
5317 c[2] *= rsurface.ent_color[2];
5318 c[3] *= rsurface.ent_color[3];
5320 if (r_refdef.fogenabled)
5322 for (i = 0, c = color4f;i < 6;i++, c += 4)
5324 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5326 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5327 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5328 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5331 R_Mesh_ResetTextureState();
5332 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5335 void R_DrawNoModel(entity_render_t *ent)
5338 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5339 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5340 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5342 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5345 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5347 vec3_t right1, right2, diff, normal;
5349 VectorSubtract (org2, org1, normal);
5351 // calculate 'right' vector for start
5352 VectorSubtract (r_refdef.view.origin, org1, diff);
5353 CrossProduct (normal, diff, right1);
5354 VectorNormalize (right1);
5356 // calculate 'right' vector for end
5357 VectorSubtract (r_refdef.view.origin, org2, diff);
5358 CrossProduct (normal, diff, right2);
5359 VectorNormalize (right2);
5361 vert[ 0] = org1[0] + width * right1[0];
5362 vert[ 1] = org1[1] + width * right1[1];
5363 vert[ 2] = org1[2] + width * right1[2];
5364 vert[ 3] = org1[0] - width * right1[0];
5365 vert[ 4] = org1[1] - width * right1[1];
5366 vert[ 5] = org1[2] - width * right1[2];
5367 vert[ 6] = org2[0] - width * right2[0];
5368 vert[ 7] = org2[1] - width * right2[1];
5369 vert[ 8] = org2[2] - width * right2[2];
5370 vert[ 9] = org2[0] + width * right2[0];
5371 vert[10] = org2[1] + width * right2[1];
5372 vert[11] = org2[2] + width * right2[2];
5375 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)
5377 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5378 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5379 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5380 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5381 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5382 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5383 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5384 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5385 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5386 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5387 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5388 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5391 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5396 VectorSet(v, x, y, z);
5397 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5398 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5400 if (i == mesh->numvertices)
5402 if (mesh->numvertices < mesh->maxvertices)
5404 VectorCopy(v, vertex3f);
5405 mesh->numvertices++;
5407 return mesh->numvertices;
5413 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5417 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5418 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5419 e = mesh->element3i + mesh->numtriangles * 3;
5420 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5422 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5423 if (mesh->numtriangles < mesh->maxtriangles)
5428 mesh->numtriangles++;
5430 element[1] = element[2];
5434 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5438 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5439 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5440 e = mesh->element3i + mesh->numtriangles * 3;
5441 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5443 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5444 if (mesh->numtriangles < mesh->maxtriangles)
5449 mesh->numtriangles++;
5451 element[1] = element[2];
5455 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5456 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5458 int planenum, planenum2;
5461 mplane_t *plane, *plane2;
5463 double temppoints[2][256*3];
5464 // figure out how large a bounding box we need to properly compute this brush
5466 for (w = 0;w < numplanes;w++)
5467 maxdist = max(maxdist, fabs(planes[w].dist));
5468 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5469 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5470 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5474 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5475 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5477 if (planenum2 == planenum)
5479 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);
5482 if (tempnumpoints < 3)
5484 // generate elements forming a triangle fan for this polygon
5485 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5489 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)
5491 texturelayer_t *layer;
5492 layer = t->currentlayers + t->currentnumlayers++;
5494 layer->depthmask = depthmask;
5495 layer->blendfunc1 = blendfunc1;
5496 layer->blendfunc2 = blendfunc2;
5497 layer->texture = texture;
5498 layer->texmatrix = *matrix;
5499 layer->color[0] = r * r_refdef.view.colorscale;
5500 layer->color[1] = g * r_refdef.view.colorscale;
5501 layer->color[2] = b * r_refdef.view.colorscale;
5502 layer->color[3] = a;
5505 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5508 index = parms[2] + r_refdef.scene.time * parms[3];
5509 index -= floor(index);
5513 case Q3WAVEFUNC_NONE:
5514 case Q3WAVEFUNC_NOISE:
5515 case Q3WAVEFUNC_COUNT:
5518 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5519 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5520 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5521 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5522 case Q3WAVEFUNC_TRIANGLE:
5524 f = index - floor(index);
5535 return (float)(parms[0] + parms[1] * f);
5538 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5543 matrix4x4_t matrix, temp;
5544 switch(tcmod->tcmod)
5548 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5549 matrix = r_waterscrollmatrix;
5551 matrix = identitymatrix;
5553 case Q3TCMOD_ENTITYTRANSLATE:
5554 // this is used in Q3 to allow the gamecode to control texcoord
5555 // scrolling on the entity, which is not supported in darkplaces yet.
5556 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5558 case Q3TCMOD_ROTATE:
5559 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5560 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5561 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5564 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5566 case Q3TCMOD_SCROLL:
5567 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5569 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5570 w = (int) tcmod->parms[0];
5571 h = (int) tcmod->parms[1];
5572 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5574 idx = (int) floor(f * w * h);
5575 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5577 case Q3TCMOD_STRETCH:
5578 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5579 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5581 case Q3TCMOD_TRANSFORM:
5582 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5583 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5584 VectorSet(tcmat + 6, 0 , 0 , 1);
5585 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5586 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5588 case Q3TCMOD_TURBULENT:
5589 // this is handled in the RSurf_PrepareVertices function
5590 matrix = identitymatrix;
5594 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5597 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5599 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5600 char name[MAX_QPATH];
5601 skinframe_t *skinframe;
5602 unsigned char pixels[296*194];
5603 strlcpy(cache->name, skinname, sizeof(cache->name));
5604 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5605 if (developer_loading.integer)
5606 Con_Printf("loading %s\n", name);
5607 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5608 if (!skinframe || !skinframe->base)
5611 fs_offset_t filesize;
5613 f = FS_LoadFile(name, tempmempool, true, &filesize);
5616 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5617 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5621 cache->skinframe = skinframe;
5624 texture_t *R_GetCurrentTexture(texture_t *t)
5627 const entity_render_t *ent = rsurface.entity;
5628 dp_model_t *model = ent->model;
5629 q3shaderinfo_layer_tcmod_t *tcmod;
5631 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5632 return t->currentframe;
5633 t->update_lastrenderframe = r_frame;
5634 t->update_lastrenderentity = (void *)ent;
5636 // switch to an alternate material if this is a q1bsp animated material
5638 texture_t *texture = t;
5639 int s = rsurface.ent_skinnum;
5640 if ((unsigned int)s >= (unsigned int)model->numskins)
5642 if (model->skinscenes)
5644 if (model->skinscenes[s].framecount > 1)
5645 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5647 s = model->skinscenes[s].firstframe;
5650 t = t + s * model->num_surfaces;
5653 // use an alternate animation if the entity's frame is not 0,
5654 // and only if the texture has an alternate animation
5655 if (rsurface.frameblend[0].subframe != 0 && t->anim_total[1])
5656 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5658 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5660 texture->currentframe = t;
5663 // update currentskinframe to be a qw skin or animation frame
5664 if (rsurface.ent_qwskin >= 0)
5666 i = rsurface.ent_qwskin;
5667 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5669 r_qwskincache_size = cl.maxclients;
5671 Mem_Free(r_qwskincache);
5672 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5674 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5675 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5676 t->currentskinframe = r_qwskincache[i].skinframe;
5677 if (t->currentskinframe == NULL)
5678 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5680 else if (t->numskinframes >= 2)
5681 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5682 if (t->backgroundnumskinframes >= 2)
5683 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5685 t->currentmaterialflags = t->basematerialflags;
5686 t->currentalpha = rsurface.ent_color[3];
5687 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5688 t->currentalpha *= r_wateralpha.value;
5689 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5690 t->currentalpha *= t->r_water_wateralpha;
5691 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5692 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5693 if (!(rsurface.ent_flags & RENDER_LIGHT))
5694 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5695 else if (rsurface.modeltexcoordlightmap2f == NULL)
5697 // pick a model lighting mode
5698 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5699 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5701 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5703 if (rsurface.ent_flags & RENDER_ADDITIVE)
5704 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5705 else if (t->currentalpha < 1)
5706 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5707 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5708 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5709 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5710 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5711 if (t->backgroundnumskinframes)
5712 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5713 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5715 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5716 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5719 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5721 // there is no tcmod
5722 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5724 t->currenttexmatrix = r_waterscrollmatrix;
5725 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5727 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5729 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5730 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5733 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5734 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5735 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5736 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5738 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5739 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5740 t->glosstexture = r_texture_black;
5741 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5742 t->backgroundglosstexture = r_texture_black;
5743 t->specularpower = r_shadow_glossexponent.value;
5744 // TODO: store reference values for these in the texture?
5745 t->specularscale = 0;
5746 if (r_shadow_gloss.integer > 0)
5748 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5750 if (r_shadow_glossintensity.value > 0)
5752 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5753 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5754 t->specularscale = r_shadow_glossintensity.value;
5757 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5759 t->glosstexture = r_texture_white;
5760 t->backgroundglosstexture = r_texture_white;
5761 t->specularscale = r_shadow_gloss2intensity.value;
5762 t->specularpower = r_shadow_gloss2exponent.value;
5765 t->specularscale *= t->specularscalemod;
5766 t->specularpower *= t->specularpowermod;
5768 // lightmaps mode looks bad with dlights using actual texturing, so turn
5769 // off the colormap and glossmap, but leave the normalmap on as it still
5770 // accurately represents the shading involved
5771 if (gl_lightmaps.integer)
5773 t->basetexture = r_texture_grey128;
5774 t->backgroundbasetexture = NULL;
5775 t->specularscale = 0;
5776 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5779 Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5780 VectorClear(t->dlightcolor);
5781 t->currentnumlayers = 0;
5782 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5785 int blendfunc1, blendfunc2;
5787 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5789 blendfunc1 = GL_SRC_ALPHA;
5790 blendfunc2 = GL_ONE;
5792 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5794 blendfunc1 = GL_SRC_ALPHA;
5795 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5797 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5799 blendfunc1 = t->customblendfunc[0];
5800 blendfunc2 = t->customblendfunc[1];
5804 blendfunc1 = GL_ONE;
5805 blendfunc2 = GL_ZERO;
5807 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5808 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5809 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5810 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5812 // fullbright is not affected by r_refdef.lightmapintensity
5813 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]);
5814 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5815 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]);
5816 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5817 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]);
5821 vec3_t ambientcolor;
5823 // set the color tint used for lights affecting this surface
5824 VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5826 // q3bsp has no lightmap updates, so the lightstylevalue that
5827 // would normally be baked into the lightmap must be
5828 // applied to the color
5829 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5830 if (model->type == mod_brushq3)
5831 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5832 colorscale *= r_refdef.lightmapintensity;
5833 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5834 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5835 // basic lit geometry
5836 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]);
5837 // add pants/shirt if needed
5838 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5839 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]);
5840 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5841 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]);
5842 // now add ambient passes if needed
5843 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5845 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]);
5846 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5847 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]);
5848 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5849 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]);
5852 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5853 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]);
5854 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5856 // if this is opaque use alpha blend which will darken the earlier
5859 // if this is an alpha blended material, all the earlier passes
5860 // were darkened by fog already, so we only need to add the fog
5861 // color ontop through the fog mask texture
5863 // if this is an additive blended material, all the earlier passes
5864 // were darkened by fog already, and we should not add fog color
5865 // (because the background was not darkened, there is no fog color
5866 // that was lost behind it).
5867 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]);
5871 return t->currentframe;
5874 rsurfacestate_t rsurface;
5876 void R_Mesh_ResizeArrays(int newvertices)
5879 if (rsurface.array_size >= newvertices)
5881 if (rsurface.array_modelvertex3f)
5882 Mem_Free(rsurface.array_modelvertex3f);
5883 rsurface.array_size = (newvertices + 1023) & ~1023;
5884 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5885 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5886 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5887 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5888 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5889 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5890 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5891 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5892 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5893 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5894 rsurface.array_color4f = base + rsurface.array_size * 27;
5895 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5898 void RSurf_ActiveWorldEntity(void)
5900 dp_model_t *model = r_refdef.scene.worldmodel;
5901 //if (rsurface.entity == r_refdef.scene.worldentity)
5903 rsurface.entity = r_refdef.scene.worldentity;
5904 rsurface.ent_skinnum = 0;
5905 rsurface.ent_qwskin = -1;
5906 rsurface.ent_shadertime = 0;
5907 Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
5908 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
5909 if (rsurface.array_size < model->surfmesh.num_vertices)
5910 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5911 rsurface.matrix = identitymatrix;
5912 rsurface.inversematrix = identitymatrix;
5913 rsurface.matrixscale = 1;
5914 rsurface.inversematrixscale = 1;
5915 R_Mesh_Matrix(&identitymatrix);
5916 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5917 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
5918 rsurface.fograngerecip = r_refdef.fograngerecip;
5919 rsurface.fogheightfade = r_refdef.fogheightfade;
5920 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
5921 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
5922 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5923 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5924 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5925 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5926 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5927 VectorSet(rsurface.glowmod, 1, 1, 1);
5928 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5929 rsurface.frameblend[0].lerp = 1;
5930 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5931 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5932 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5933 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5934 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5935 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5936 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5937 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5938 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5939 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5940 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5941 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5942 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5943 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5944 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5945 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5946 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5947 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5948 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5949 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5950 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5951 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5952 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5953 rsurface.modelelement3i = model->surfmesh.data_element3i;
5954 rsurface.modelelement3s = model->surfmesh.data_element3s;
5955 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5956 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5957 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5958 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5959 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5960 rsurface.modelsurfaces = model->data_surfaces;
5961 rsurface.generatedvertex = false;
5962 rsurface.vertex3f = rsurface.modelvertex3f;
5963 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5964 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5965 rsurface.svector3f = rsurface.modelsvector3f;
5966 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5967 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5968 rsurface.tvector3f = rsurface.modeltvector3f;
5969 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5970 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5971 rsurface.normal3f = rsurface.modelnormal3f;
5972 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5973 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5974 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5977 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5979 dp_model_t *model = ent->model;
5980 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5982 rsurface.entity = (entity_render_t *)ent;
5983 rsurface.ent_skinnum = ent->skinnum;
5984 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;
5985 rsurface.ent_shadertime = ent->shadertime;
5986 Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
5987 rsurface.ent_flags = ent->flags;
5988 if (rsurface.array_size < model->surfmesh.num_vertices)
5989 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5990 rsurface.matrix = ent->matrix;
5991 rsurface.inversematrix = ent->inversematrix;
5992 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
5993 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
5994 R_Mesh_Matrix(&rsurface.matrix);
5995 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
5996 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
5997 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
5998 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
5999 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6000 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6001 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6002 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6003 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6004 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6005 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6006 VectorCopy(ent->glowmod, rsurface.glowmod);
6007 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6008 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6009 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6010 if (ent->model->brush.submodel)
6012 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6013 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6015 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6017 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6019 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6020 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6021 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6022 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6024 else if (wanttangents)
6026 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6027 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6028 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6029 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6030 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6032 else if (wantnormals)
6034 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6035 rsurface.modelsvector3f = NULL;
6036 rsurface.modeltvector3f = NULL;
6037 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6038 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6042 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6043 rsurface.modelsvector3f = NULL;
6044 rsurface.modeltvector3f = NULL;
6045 rsurface.modelnormal3f = NULL;
6046 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6048 rsurface.modelvertex3f_bufferobject = 0;
6049 rsurface.modelvertex3f_bufferoffset = 0;
6050 rsurface.modelsvector3f_bufferobject = 0;
6051 rsurface.modelsvector3f_bufferoffset = 0;
6052 rsurface.modeltvector3f_bufferobject = 0;
6053 rsurface.modeltvector3f_bufferoffset = 0;
6054 rsurface.modelnormal3f_bufferobject = 0;
6055 rsurface.modelnormal3f_bufferoffset = 0;
6056 rsurface.generatedvertex = true;
6060 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6061 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6062 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6063 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6064 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6065 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6066 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6067 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6068 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6069 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6070 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6071 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6072 rsurface.generatedvertex = false;
6074 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6075 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6076 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6077 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6078 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6079 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6080 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6081 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6082 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6083 rsurface.modelelement3i = model->surfmesh.data_element3i;
6084 rsurface.modelelement3s = model->surfmesh.data_element3s;
6085 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6086 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6087 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6088 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6089 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6090 rsurface.modelsurfaces = model->data_surfaces;
6091 rsurface.vertex3f = rsurface.modelvertex3f;
6092 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6093 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6094 rsurface.svector3f = rsurface.modelsvector3f;
6095 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6096 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6097 rsurface.tvector3f = rsurface.modeltvector3f;
6098 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6099 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6100 rsurface.normal3f = rsurface.modelnormal3f;
6101 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6102 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6103 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6106 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)
6108 rsurface.entity = r_refdef.scene.worldentity;
6109 rsurface.ent_skinnum = 0;
6110 rsurface.ent_qwskin = -1;
6111 rsurface.ent_shadertime = shadertime;
6112 Vector4Set(rsurface.ent_color, r, g, b, a);
6113 rsurface.ent_flags = entflags;
6114 rsurface.modelnum_vertices = numvertices;
6115 rsurface.modelnum_triangles = numtriangles;
6116 if (rsurface.array_size < rsurface.modelnum_vertices)
6117 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6118 rsurface.matrix = *matrix;
6119 rsurface.inversematrix = *inversematrix;
6120 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6121 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6122 R_Mesh_Matrix(&rsurface.matrix);
6123 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6124 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6125 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6126 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6127 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6128 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6129 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6130 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6131 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6132 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6133 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6134 VectorSet(rsurface.glowmod, 1, 1, 1);
6135 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6136 rsurface.frameblend[0].lerp = 1;
6137 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6138 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6141 rsurface.modelvertex3f = vertex3f;
6142 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6143 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6144 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6146 else if (wantnormals)
6148 rsurface.modelvertex3f = vertex3f;
6149 rsurface.modelsvector3f = NULL;
6150 rsurface.modeltvector3f = NULL;
6151 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6155 rsurface.modelvertex3f = vertex3f;
6156 rsurface.modelsvector3f = NULL;
6157 rsurface.modeltvector3f = NULL;
6158 rsurface.modelnormal3f = NULL;
6160 rsurface.modelvertex3f_bufferobject = 0;
6161 rsurface.modelvertex3f_bufferoffset = 0;
6162 rsurface.modelsvector3f_bufferobject = 0;
6163 rsurface.modelsvector3f_bufferoffset = 0;
6164 rsurface.modeltvector3f_bufferobject = 0;
6165 rsurface.modeltvector3f_bufferoffset = 0;
6166 rsurface.modelnormal3f_bufferobject = 0;
6167 rsurface.modelnormal3f_bufferoffset = 0;
6168 rsurface.generatedvertex = true;
6169 rsurface.modellightmapcolor4f = color4f;
6170 rsurface.modellightmapcolor4f_bufferobject = 0;
6171 rsurface.modellightmapcolor4f_bufferoffset = 0;
6172 rsurface.modeltexcoordtexture2f = texcoord2f;
6173 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6174 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6175 rsurface.modeltexcoordlightmap2f = NULL;
6176 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6177 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6178 rsurface.modelelement3i = element3i;
6179 rsurface.modelelement3s = element3s;
6180 rsurface.modelelement3i_bufferobject = 0;
6181 rsurface.modelelement3s_bufferobject = 0;
6182 rsurface.modellightmapoffsets = NULL;
6183 rsurface.modelsurfaces = NULL;
6184 rsurface.vertex3f = rsurface.modelvertex3f;
6185 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6186 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6187 rsurface.svector3f = rsurface.modelsvector3f;
6188 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6189 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6190 rsurface.tvector3f = rsurface.modeltvector3f;
6191 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6192 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6193 rsurface.normal3f = rsurface.modelnormal3f;
6194 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6195 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6196 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6198 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6200 if ((wantnormals || wanttangents) && !normal3f)
6201 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6202 if (wanttangents && !svector3f)
6203 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);
6207 float RSurf_FogPoint(const float *v)
6209 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6210 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6211 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6212 float FogHeightFade = r_refdef.fogheightfade;
6214 unsigned int fogmasktableindex;
6215 if (r_refdef.fogplaneviewabove)
6216 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6218 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6219 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6220 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6223 float RSurf_FogVertex(const float *v)
6225 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6226 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6227 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6228 float FogHeightFade = rsurface.fogheightfade;
6230 unsigned int fogmasktableindex;
6231 if (r_refdef.fogplaneviewabove)
6232 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6234 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6235 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6236 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6239 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6240 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6243 int texturesurfaceindex;
6248 const float *v1, *in_tc;
6250 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6252 q3shaderinfo_deform_t *deform;
6253 // 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
6254 if (rsurface.generatedvertex)
6256 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6257 generatenormals = true;
6258 for (i = 0;i < Q3MAXDEFORMS;i++)
6260 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6262 generatetangents = true;
6263 generatenormals = true;
6265 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6266 generatenormals = true;
6268 if (generatenormals && !rsurface.modelnormal3f)
6270 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6271 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6272 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6273 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6275 if (generatetangents && !rsurface.modelsvector3f)
6277 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6278 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6279 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6280 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6281 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6282 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6283 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);
6286 rsurface.vertex3f = rsurface.modelvertex3f;
6287 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6288 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6289 rsurface.svector3f = rsurface.modelsvector3f;
6290 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6291 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6292 rsurface.tvector3f = rsurface.modeltvector3f;
6293 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6294 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6295 rsurface.normal3f = rsurface.modelnormal3f;
6296 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6297 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6298 // if vertices are deformed (sprite flares and things in maps, possibly
6299 // water waves, bulges and other deformations), generate them into
6300 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6301 // (may be static model data or generated data for an animated model, or
6302 // the previous deform pass)
6303 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6305 switch (deform->deform)
6308 case Q3DEFORM_PROJECTIONSHADOW:
6309 case Q3DEFORM_TEXT0:
6310 case Q3DEFORM_TEXT1:
6311 case Q3DEFORM_TEXT2:
6312 case Q3DEFORM_TEXT3:
6313 case Q3DEFORM_TEXT4:
6314 case Q3DEFORM_TEXT5:
6315 case Q3DEFORM_TEXT6:
6316 case Q3DEFORM_TEXT7:
6319 case Q3DEFORM_AUTOSPRITE:
6320 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6321 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6322 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6323 VectorNormalize(newforward);
6324 VectorNormalize(newright);
6325 VectorNormalize(newup);
6326 // make deformed versions of only the model vertices used by the specified surfaces
6327 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6329 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6330 // a single autosprite surface can contain multiple sprites...
6331 for (j = 0;j < surface->num_vertices - 3;j += 4)
6333 VectorClear(center);
6334 for (i = 0;i < 4;i++)
6335 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6336 VectorScale(center, 0.25f, center);
6337 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6338 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6339 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6340 for (i = 0;i < 4;i++)
6342 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6343 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6346 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);
6347 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);
6349 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6350 rsurface.vertex3f_bufferobject = 0;
6351 rsurface.vertex3f_bufferoffset = 0;
6352 rsurface.svector3f = rsurface.array_deformedsvector3f;
6353 rsurface.svector3f_bufferobject = 0;
6354 rsurface.svector3f_bufferoffset = 0;
6355 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6356 rsurface.tvector3f_bufferobject = 0;
6357 rsurface.tvector3f_bufferoffset = 0;
6358 rsurface.normal3f = rsurface.array_deformednormal3f;
6359 rsurface.normal3f_bufferobject = 0;
6360 rsurface.normal3f_bufferoffset = 0;
6362 case Q3DEFORM_AUTOSPRITE2:
6363 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6364 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6365 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6366 VectorNormalize(newforward);
6367 VectorNormalize(newright);
6368 VectorNormalize(newup);
6369 // make deformed versions of only the model vertices used by the specified surfaces
6370 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6372 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6373 const float *v1, *v2;
6383 memset(shortest, 0, sizeof(shortest));
6384 // a single autosprite surface can contain multiple sprites...
6385 for (j = 0;j < surface->num_vertices - 3;j += 4)
6387 VectorClear(center);
6388 for (i = 0;i < 4;i++)
6389 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6390 VectorScale(center, 0.25f, center);
6391 // find the two shortest edges, then use them to define the
6392 // axis vectors for rotating around the central axis
6393 for (i = 0;i < 6;i++)
6395 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6396 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6398 Debug_PolygonBegin(NULL, 0);
6399 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6400 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);
6401 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6404 l = VectorDistance2(v1, v2);
6405 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6407 l += (1.0f / 1024.0f);
6408 if (shortest[0].length2 > l || i == 0)
6410 shortest[1] = shortest[0];
6411 shortest[0].length2 = l;
6412 shortest[0].v1 = v1;
6413 shortest[0].v2 = v2;
6415 else if (shortest[1].length2 > l || i == 1)
6417 shortest[1].length2 = l;
6418 shortest[1].v1 = v1;
6419 shortest[1].v2 = v2;
6422 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6423 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6425 Debug_PolygonBegin(NULL, 0);
6426 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6427 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);
6428 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6431 // this calculates the right vector from the shortest edge
6432 // and the up vector from the edge midpoints
6433 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6434 VectorNormalize(right);
6435 VectorSubtract(end, start, up);
6436 VectorNormalize(up);
6437 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6438 VectorSubtract(rsurface.localvieworigin, center, forward);
6439 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6440 VectorNegate(forward, forward);
6441 VectorReflect(forward, 0, up, forward);
6442 VectorNormalize(forward);
6443 CrossProduct(up, forward, newright);
6444 VectorNormalize(newright);
6446 Debug_PolygonBegin(NULL, 0);
6447 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);
6448 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6449 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6453 Debug_PolygonBegin(NULL, 0);
6454 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6455 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6456 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6459 // rotate the quad around the up axis vector, this is made
6460 // especially easy by the fact we know the quad is flat,
6461 // so we only have to subtract the center position and
6462 // measure distance along the right vector, and then
6463 // multiply that by the newright vector and add back the
6465 // we also need to subtract the old position to undo the
6466 // displacement from the center, which we do with a
6467 // DotProduct, the subtraction/addition of center is also
6468 // optimized into DotProducts here
6469 l = DotProduct(right, center);
6470 for (i = 0;i < 4;i++)
6472 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6473 f = DotProduct(right, v1) - l;
6474 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6477 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);
6478 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);
6480 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6481 rsurface.vertex3f_bufferobject = 0;
6482 rsurface.vertex3f_bufferoffset = 0;
6483 rsurface.svector3f = rsurface.array_deformedsvector3f;
6484 rsurface.svector3f_bufferobject = 0;
6485 rsurface.svector3f_bufferoffset = 0;
6486 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6487 rsurface.tvector3f_bufferobject = 0;
6488 rsurface.tvector3f_bufferoffset = 0;
6489 rsurface.normal3f = rsurface.array_deformednormal3f;
6490 rsurface.normal3f_bufferobject = 0;
6491 rsurface.normal3f_bufferoffset = 0;
6493 case Q3DEFORM_NORMAL:
6494 // deform the normals to make reflections wavey
6495 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6497 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6498 for (j = 0;j < surface->num_vertices;j++)
6501 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6502 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6503 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6504 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6505 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6506 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6507 VectorNormalize(normal);
6509 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);
6511 rsurface.svector3f = rsurface.array_deformedsvector3f;
6512 rsurface.svector3f_bufferobject = 0;
6513 rsurface.svector3f_bufferoffset = 0;
6514 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6515 rsurface.tvector3f_bufferobject = 0;
6516 rsurface.tvector3f_bufferoffset = 0;
6517 rsurface.normal3f = rsurface.array_deformednormal3f;
6518 rsurface.normal3f_bufferobject = 0;
6519 rsurface.normal3f_bufferoffset = 0;
6522 // deform vertex array to make wavey water and flags and such
6523 waveparms[0] = deform->waveparms[0];
6524 waveparms[1] = deform->waveparms[1];
6525 waveparms[2] = deform->waveparms[2];
6526 waveparms[3] = deform->waveparms[3];
6527 // this is how a divisor of vertex influence on deformation
6528 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6529 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6530 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6532 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6533 for (j = 0;j < surface->num_vertices;j++)
6535 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6536 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6537 // if the wavefunc depends on time, evaluate it per-vertex
6540 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6541 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6543 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6546 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6547 rsurface.vertex3f_bufferobject = 0;
6548 rsurface.vertex3f_bufferoffset = 0;
6550 case Q3DEFORM_BULGE:
6551 // deform vertex array to make the surface have moving bulges
6552 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6554 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6555 for (j = 0;j < surface->num_vertices;j++)
6557 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6558 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6561 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6562 rsurface.vertex3f_bufferobject = 0;
6563 rsurface.vertex3f_bufferoffset = 0;
6566 // deform vertex array
6567 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6568 VectorScale(deform->parms, scale, waveparms);
6569 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6571 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6572 for (j = 0;j < surface->num_vertices;j++)
6573 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6575 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6576 rsurface.vertex3f_bufferobject = 0;
6577 rsurface.vertex3f_bufferoffset = 0;
6581 // generate texcoords based on the chosen texcoord source
6582 switch(rsurface.texture->tcgen.tcgen)
6585 case Q3TCGEN_TEXTURE:
6586 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6587 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6588 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6590 case Q3TCGEN_LIGHTMAP:
6591 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6592 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6593 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6595 case Q3TCGEN_VECTOR:
6596 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6598 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6599 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)
6601 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6602 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6605 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6606 rsurface.texcoordtexture2f_bufferobject = 0;
6607 rsurface.texcoordtexture2f_bufferoffset = 0;
6609 case Q3TCGEN_ENVIRONMENT:
6610 // make environment reflections using a spheremap
6611 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6613 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6614 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6615 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6616 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6617 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6619 // identical to Q3A's method, but executed in worldspace so
6620 // carried models can be shiny too
6622 float viewer[3], d, reflected[3], worldreflected[3];
6624 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6625 // VectorNormalize(viewer);
6627 d = DotProduct(normal, viewer);
6629 reflected[0] = normal[0]*2*d - viewer[0];
6630 reflected[1] = normal[1]*2*d - viewer[1];
6631 reflected[2] = normal[2]*2*d - viewer[2];
6632 // note: this is proportinal to viewer, so we can normalize later
6634 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6635 VectorNormalize(worldreflected);
6637 // note: this sphere map only uses world x and z!
6638 // so positive and negative y will LOOK THE SAME.
6639 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6640 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6643 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6644 rsurface.texcoordtexture2f_bufferobject = 0;
6645 rsurface.texcoordtexture2f_bufferoffset = 0;
6648 // the only tcmod that needs software vertex processing is turbulent, so
6649 // check for it here and apply the changes if needed
6650 // and we only support that as the first one
6651 // (handling a mixture of turbulent and other tcmods would be problematic
6652 // without punting it entirely to a software path)
6653 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6655 amplitude = rsurface.texture->tcmods[0].parms[1];
6656 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6657 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6659 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6660 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)
6662 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6663 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6666 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6667 rsurface.texcoordtexture2f_bufferobject = 0;
6668 rsurface.texcoordtexture2f_bufferoffset = 0;
6670 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6671 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6672 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6673 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6676 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6679 const msurface_t *surface = texturesurfacelist[0];
6680 const msurface_t *surface2;
6685 // TODO: lock all array ranges before render, rather than on each surface
6686 if (texturenumsurfaces == 1)
6688 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6689 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);
6691 else if (r_batchmode.integer == 2)
6693 #define MAXBATCHTRIANGLES 4096
6694 int batchtriangles = 0;
6695 int batchelements[MAXBATCHTRIANGLES*3];
6696 for (i = 0;i < texturenumsurfaces;i = j)
6698 surface = texturesurfacelist[i];
6700 if (surface->num_triangles > MAXBATCHTRIANGLES)
6702 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);
6705 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6706 batchtriangles = surface->num_triangles;
6707 firstvertex = surface->num_firstvertex;
6708 endvertex = surface->num_firstvertex + surface->num_vertices;
6709 for (;j < texturenumsurfaces;j++)
6711 surface2 = texturesurfacelist[j];
6712 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6714 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6715 batchtriangles += surface2->num_triangles;
6716 firstvertex = min(firstvertex, surface2->num_firstvertex);
6717 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6719 surface2 = texturesurfacelist[j-1];
6720 numvertices = endvertex - firstvertex;
6721 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6724 else if (r_batchmode.integer == 1)
6726 for (i = 0;i < texturenumsurfaces;i = j)
6728 surface = texturesurfacelist[i];
6729 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6730 if (texturesurfacelist[j] != surface2)
6732 surface2 = texturesurfacelist[j-1];
6733 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6734 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6735 GL_LockArrays(surface->num_firstvertex, numvertices);
6736 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6741 for (i = 0;i < texturenumsurfaces;i++)
6743 surface = texturesurfacelist[i];
6744 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6745 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6750 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6752 int i, planeindex, vertexindex;
6756 r_waterstate_waterplane_t *p, *bestp;
6757 const msurface_t *surface;
6758 if (r_waterstate.renderingscene)
6760 for (i = 0;i < texturenumsurfaces;i++)
6762 surface = texturesurfacelist[i];
6763 if (lightmaptexunit >= 0)
6764 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6765 if (deluxemaptexunit >= 0)
6766 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6767 // pick the closest matching water plane
6770 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6773 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6775 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6776 d += fabs(PlaneDiff(vert, &p->plane));
6778 if (bestd > d || !bestp)
6786 if (refractiontexunit >= 0)
6787 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6788 if (reflectiontexunit >= 0)
6789 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6793 if (refractiontexunit >= 0)
6794 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6795 if (reflectiontexunit >= 0)
6796 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6798 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6799 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);
6803 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6807 const msurface_t *surface = texturesurfacelist[0];
6808 const msurface_t *surface2;
6813 // TODO: lock all array ranges before render, rather than on each surface
6814 if (texturenumsurfaces == 1)
6816 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6817 if (deluxemaptexunit >= 0)
6818 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6819 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6820 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);
6822 else if (r_batchmode.integer == 2)
6824 #define MAXBATCHTRIANGLES 4096
6825 int batchtriangles = 0;
6826 int batchelements[MAXBATCHTRIANGLES*3];
6827 for (i = 0;i < texturenumsurfaces;i = j)
6829 surface = texturesurfacelist[i];
6830 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6831 if (deluxemaptexunit >= 0)
6832 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6834 if (surface->num_triangles > MAXBATCHTRIANGLES)
6836 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);
6839 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6840 batchtriangles = surface->num_triangles;
6841 firstvertex = surface->num_firstvertex;
6842 endvertex = surface->num_firstvertex + surface->num_vertices;
6843 for (;j < texturenumsurfaces;j++)
6845 surface2 = texturesurfacelist[j];
6846 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6848 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6849 batchtriangles += surface2->num_triangles;
6850 firstvertex = min(firstvertex, surface2->num_firstvertex);
6851 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6853 surface2 = texturesurfacelist[j-1];
6854 numvertices = endvertex - firstvertex;
6855 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6858 else if (r_batchmode.integer == 1)
6861 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6862 for (i = 0;i < texturenumsurfaces;i = j)
6864 surface = texturesurfacelist[i];
6865 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6866 if (texturesurfacelist[j] != surface2)
6868 Con_Printf(" %i", j - i);
6871 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6873 for (i = 0;i < texturenumsurfaces;i = j)
6875 surface = texturesurfacelist[i];
6876 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6877 if (deluxemaptexunit >= 0)
6878 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6879 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6880 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6883 Con_Printf(" %i", j - i);
6885 surface2 = texturesurfacelist[j-1];
6886 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6887 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6888 GL_LockArrays(surface->num_firstvertex, numvertices);
6889 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6897 for (i = 0;i < texturenumsurfaces;i++)
6899 surface = texturesurfacelist[i];
6900 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6901 if (deluxemaptexunit >= 0)
6902 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6903 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6904 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);
6909 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6912 int texturesurfaceindex;
6913 if (r_showsurfaces.integer == 2)
6915 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6917 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6918 for (j = 0;j < surface->num_triangles;j++)
6920 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6921 GL_Color(f, f, f, 1);
6922 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6928 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6930 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6931 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6932 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);
6933 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6934 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);
6939 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6941 int texturesurfaceindex;
6945 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6947 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6948 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)
6956 rsurface.lightmapcolor4f = rsurface.array_color4f;
6957 rsurface.lightmapcolor4f_bufferobject = 0;
6958 rsurface.lightmapcolor4f_bufferoffset = 0;
6961 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6963 int texturesurfaceindex;
6969 if (rsurface.lightmapcolor4f)
6971 // generate color arrays for the surfaces in this list
6972 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6974 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6975 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)
6977 f = RSurf_FogVertex(v);
6987 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6989 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6990 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)
6992 f = RSurf_FogVertex(v);
7000 rsurface.lightmapcolor4f = rsurface.array_color4f;
7001 rsurface.lightmapcolor4f_bufferobject = 0;
7002 rsurface.lightmapcolor4f_bufferoffset = 0;
7005 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7007 int texturesurfaceindex;
7013 if (!rsurface.lightmapcolor4f)
7015 // generate color arrays for the surfaces in this list
7016 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7018 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7019 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)
7021 f = RSurf_FogVertex(v);
7022 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7023 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7024 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7028 rsurface.lightmapcolor4f = rsurface.array_color4f;
7029 rsurface.lightmapcolor4f_bufferobject = 0;
7030 rsurface.lightmapcolor4f_bufferoffset = 0;
7033 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7035 int texturesurfaceindex;
7039 if (!rsurface.lightmapcolor4f)
7041 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7043 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7044 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)
7052 rsurface.lightmapcolor4f = rsurface.array_color4f;
7053 rsurface.lightmapcolor4f_bufferobject = 0;
7054 rsurface.lightmapcolor4f_bufferoffset = 0;
7057 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7059 int texturesurfaceindex;
7063 if (!rsurface.lightmapcolor4f)
7065 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7067 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7068 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)
7070 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7071 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7072 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7076 rsurface.lightmapcolor4f = rsurface.array_color4f;
7077 rsurface.lightmapcolor4f_bufferobject = 0;
7078 rsurface.lightmapcolor4f_bufferoffset = 0;
7081 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7084 rsurface.lightmapcolor4f = NULL;
7085 rsurface.lightmapcolor4f_bufferobject = 0;
7086 rsurface.lightmapcolor4f_bufferoffset = 0;
7087 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7088 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7089 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7090 GL_Color(r, g, b, a);
7091 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7094 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7096 // TODO: optimize applyfog && applycolor case
7097 // just apply fog if necessary, and tint the fog color array if necessary
7098 rsurface.lightmapcolor4f = NULL;
7099 rsurface.lightmapcolor4f_bufferobject = 0;
7100 rsurface.lightmapcolor4f_bufferoffset = 0;
7101 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7102 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7103 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7104 GL_Color(r, g, b, a);
7105 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7108 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7110 int texturesurfaceindex;
7114 if (texturesurfacelist[0]->lightmapinfo)
7116 // generate color arrays for the surfaces in this list
7117 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7119 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7120 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7122 if (surface->lightmapinfo->samples)
7124 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7125 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7126 VectorScale(lm, scale, c);
7127 if (surface->lightmapinfo->styles[1] != 255)
7129 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7131 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7132 VectorMA(c, scale, lm, c);
7133 if (surface->lightmapinfo->styles[2] != 255)
7136 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7137 VectorMA(c, scale, lm, c);
7138 if (surface->lightmapinfo->styles[3] != 255)
7141 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7142 VectorMA(c, scale, lm, c);
7152 rsurface.lightmapcolor4f = rsurface.array_color4f;
7153 rsurface.lightmapcolor4f_bufferobject = 0;
7154 rsurface.lightmapcolor4f_bufferoffset = 0;
7158 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7159 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7160 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7162 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7163 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7164 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7165 GL_Color(r, g, b, a);
7166 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7169 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7171 int texturesurfaceindex;
7178 vec3_t ambientcolor;
7179 vec3_t diffusecolor;
7183 VectorCopy(rsurface.modellight_lightdir, lightdir);
7184 f = 0.5f * r_refdef.lightmapintensity;
7185 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7186 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7187 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7188 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7189 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7190 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7192 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7194 // generate color arrays for the surfaces in this list
7195 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7197 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7198 int numverts = surface->num_vertices;
7199 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7200 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7201 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7202 // q3-style directional shading
7203 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7205 if ((f = DotProduct(n, lightdir)) > 0)
7206 VectorMA(ambientcolor, f, diffusecolor, c);
7208 VectorCopy(ambientcolor, c);
7216 rsurface.lightmapcolor4f = rsurface.array_color4f;
7217 rsurface.lightmapcolor4f_bufferobject = 0;
7218 rsurface.lightmapcolor4f_bufferoffset = 0;
7219 *applycolor = false;
7223 *r = ambientcolor[0];
7224 *g = ambientcolor[1];
7225 *b = ambientcolor[2];
7226 rsurface.lightmapcolor4f = NULL;
7227 rsurface.lightmapcolor4f_bufferobject = 0;
7228 rsurface.lightmapcolor4f_bufferoffset = 0;
7232 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7234 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7235 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7236 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7237 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7238 GL_Color(r, g, b, a);
7239 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7242 void RSurf_SetupDepthAndCulling(void)
7244 // submodels are biased to avoid z-fighting with world surfaces that they
7245 // may be exactly overlapping (avoids z-fighting artifacts on certain
7246 // doors and things in Quake maps)
7247 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7248 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7249 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7250 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7253 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7255 // transparent sky would be ridiculous
7256 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7258 R_SetupGenericShader(false);
7259 skyrenderlater = true;
7260 RSurf_SetupDepthAndCulling();
7262 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7263 // skymasking on them, and Quake3 never did sky masking (unlike
7264 // software Quake and software Quake2), so disable the sky masking
7265 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7266 // and skymasking also looks very bad when noclipping outside the
7267 // level, so don't use it then either.
7268 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7270 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7271 R_Mesh_ColorPointer(NULL, 0, 0);
7272 R_Mesh_ResetTextureState();
7273 if (skyrendermasked)
7275 R_SetupDepthOrShadowShader();
7276 // depth-only (masking)
7277 GL_ColorMask(0,0,0,0);
7278 // just to make sure that braindead drivers don't draw
7279 // anything despite that colormask...
7280 GL_BlendFunc(GL_ZERO, GL_ONE);
7284 R_SetupGenericShader(false);
7286 GL_BlendFunc(GL_ONE, GL_ZERO);
7288 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7289 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7290 if (skyrendermasked)
7291 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7293 R_Mesh_ResetTextureState();
7294 GL_Color(1, 1, 1, 1);
7297 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7299 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7302 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7303 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7304 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7305 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7306 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7307 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7308 if (rsurface.texture->backgroundcurrentskinframe)
7310 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7311 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7312 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7313 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7315 if(rsurface.texture->colormapping)
7317 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7318 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7320 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7321 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7322 R_Mesh_ColorPointer(NULL, 0, 0);
7324 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7326 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7328 // render background
7329 GL_BlendFunc(GL_ONE, GL_ZERO);
7331 GL_AlphaTest(false);
7333 GL_Color(1, 1, 1, 1);
7334 R_Mesh_ColorPointer(NULL, 0, 0);
7336 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7337 if (r_glsl_permutation)
7339 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7340 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7341 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7342 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7343 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7344 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7345 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);
7347 GL_LockArrays(0, 0);
7349 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7350 GL_DepthMask(false);
7351 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7352 R_Mesh_ColorPointer(NULL, 0, 0);
7354 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7355 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7356 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7359 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7360 if (!r_glsl_permutation)
7363 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7364 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7365 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7366 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7367 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7368 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7370 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7372 GL_BlendFunc(GL_ONE, GL_ZERO);
7374 GL_AlphaTest(false);
7378 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7379 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7380 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7383 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7385 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7386 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);
7388 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7392 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7393 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);
7395 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7397 GL_LockArrays(0, 0);
7400 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7402 // OpenGL 1.3 path - anything not completely ancient
7403 int texturesurfaceindex;
7404 qboolean applycolor;
7408 const texturelayer_t *layer;
7409 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7411 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7414 int layertexrgbscale;
7415 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7417 if (layerindex == 0)
7421 GL_AlphaTest(false);
7422 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7425 GL_DepthMask(layer->depthmask && writedepth);
7426 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7427 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7429 layertexrgbscale = 4;
7430 VectorScale(layer->color, 0.25f, layercolor);
7432 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7434 layertexrgbscale = 2;
7435 VectorScale(layer->color, 0.5f, layercolor);
7439 layertexrgbscale = 1;
7440 VectorScale(layer->color, 1.0f, layercolor);
7442 layercolor[3] = layer->color[3];
7443 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7444 R_Mesh_ColorPointer(NULL, 0, 0);
7445 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7446 switch (layer->type)
7448 case TEXTURELAYERTYPE_LITTEXTURE:
7449 memset(&m, 0, sizeof(m));
7450 m.tex[0] = R_GetTexture(r_texture_white);
7451 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7452 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7453 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7454 m.tex[1] = R_GetTexture(layer->texture);
7455 m.texmatrix[1] = layer->texmatrix;
7456 m.texrgbscale[1] = layertexrgbscale;
7457 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7458 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7459 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7460 R_Mesh_TextureState(&m);
7461 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7462 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7463 else if (rsurface.uselightmaptexture)
7464 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7466 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7468 case TEXTURELAYERTYPE_TEXTURE:
7469 memset(&m, 0, sizeof(m));
7470 m.tex[0] = R_GetTexture(layer->texture);
7471 m.texmatrix[0] = layer->texmatrix;
7472 m.texrgbscale[0] = layertexrgbscale;
7473 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7474 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7475 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7476 R_Mesh_TextureState(&m);
7477 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7479 case TEXTURELAYERTYPE_FOG:
7480 memset(&m, 0, sizeof(m));
7481 m.texrgbscale[0] = layertexrgbscale;
7484 m.tex[0] = R_GetTexture(layer->texture);
7485 m.texmatrix[0] = layer->texmatrix;
7486 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7487 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7488 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7490 R_Mesh_TextureState(&m);
7491 // generate a color array for the fog pass
7492 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7493 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7499 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7500 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)
7502 f = 1 - RSurf_FogVertex(v);
7503 c[0] = layercolor[0];
7504 c[1] = layercolor[1];
7505 c[2] = layercolor[2];
7506 c[3] = f * layercolor[3];
7509 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7512 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7514 GL_LockArrays(0, 0);
7517 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7519 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7520 GL_AlphaTest(false);
7524 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7526 // OpenGL 1.1 - crusty old voodoo path
7527 int texturesurfaceindex;
7531 const texturelayer_t *layer;
7532 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7534 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7536 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7538 if (layerindex == 0)
7542 GL_AlphaTest(false);
7543 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7546 GL_DepthMask(layer->depthmask && writedepth);
7547 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7548 R_Mesh_ColorPointer(NULL, 0, 0);
7549 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7550 switch (layer->type)
7552 case TEXTURELAYERTYPE_LITTEXTURE:
7553 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7555 // two-pass lit texture with 2x rgbscale
7556 // first the lightmap pass
7557 memset(&m, 0, sizeof(m));
7558 m.tex[0] = R_GetTexture(r_texture_white);
7559 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7560 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7561 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7562 R_Mesh_TextureState(&m);
7563 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7564 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7565 else if (rsurface.uselightmaptexture)
7566 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7568 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7569 GL_LockArrays(0, 0);
7570 // then apply the texture to it
7571 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7572 memset(&m, 0, sizeof(m));
7573 m.tex[0] = R_GetTexture(layer->texture);
7574 m.texmatrix[0] = layer->texmatrix;
7575 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7576 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7577 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7578 R_Mesh_TextureState(&m);
7579 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);
7583 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7584 memset(&m, 0, sizeof(m));
7585 m.tex[0] = R_GetTexture(layer->texture);
7586 m.texmatrix[0] = layer->texmatrix;
7587 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7588 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7589 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7590 R_Mesh_TextureState(&m);
7591 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7592 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);
7594 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);
7597 case TEXTURELAYERTYPE_TEXTURE:
7598 // singletexture unlit texture with transparency support
7599 memset(&m, 0, sizeof(m));
7600 m.tex[0] = R_GetTexture(layer->texture);
7601 m.texmatrix[0] = layer->texmatrix;
7602 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7603 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7604 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7605 R_Mesh_TextureState(&m);
7606 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);
7608 case TEXTURELAYERTYPE_FOG:
7609 // singletexture fogging
7610 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7613 memset(&m, 0, sizeof(m));
7614 m.tex[0] = R_GetTexture(layer->texture);
7615 m.texmatrix[0] = layer->texmatrix;
7616 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7617 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7618 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7619 R_Mesh_TextureState(&m);
7622 R_Mesh_ResetTextureState();
7623 // generate a color array for the fog pass
7624 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7630 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7631 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)
7633 f = 1 - RSurf_FogVertex(v);
7634 c[0] = layer->color[0];
7635 c[1] = layer->color[1];
7636 c[2] = layer->color[2];
7637 c[3] = f * layer->color[3];
7640 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7643 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7645 GL_LockArrays(0, 0);
7648 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7650 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7651 GL_AlphaTest(false);
7655 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7659 GL_AlphaTest(false);
7660 R_Mesh_ColorPointer(NULL, 0, 0);
7661 R_Mesh_ResetTextureState();
7662 R_SetupGenericShader(false);
7664 if(rsurface.texture && rsurface.texture->currentskinframe)
7666 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7667 c[3] *= rsurface.texture->currentalpha;
7677 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7679 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7680 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7681 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7684 // brighten it up (as texture value 127 means "unlit")
7685 c[0] *= 2 * r_refdef.view.colorscale;
7686 c[1] *= 2 * r_refdef.view.colorscale;
7687 c[2] *= 2 * r_refdef.view.colorscale;
7689 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7690 c[3] *= r_wateralpha.value;
7692 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7694 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7695 GL_DepthMask(false);
7697 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7699 GL_BlendFunc(GL_ONE, GL_ONE);
7700 GL_DepthMask(false);
7702 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7704 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7705 GL_DepthMask(false);
7707 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7709 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7710 GL_DepthMask(false);
7714 GL_BlendFunc(GL_ONE, GL_ZERO);
7715 GL_DepthMask(writedepth);
7718 rsurface.lightmapcolor4f = NULL;
7720 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7722 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7724 rsurface.lightmapcolor4f = NULL;
7725 rsurface.lightmapcolor4f_bufferobject = 0;
7726 rsurface.lightmapcolor4f_bufferoffset = 0;
7728 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7730 qboolean applycolor = true;
7733 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7735 r_refdef.lightmapintensity = 1;
7736 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7737 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7741 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7743 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7744 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7745 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7748 if(!rsurface.lightmapcolor4f)
7749 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7751 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7752 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7753 if(r_refdef.fogenabled)
7754 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7756 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7757 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7760 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7763 RSurf_SetupDepthAndCulling();
7764 if (r_showsurfaces.integer == 3)
7765 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7766 else if (r_glsl.integer && gl_support_fragment_shader)
7767 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7768 else if (gl_combine.integer && r_textureunits.integer >= 2)
7769 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7771 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7775 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7778 RSurf_SetupDepthAndCulling();
7779 if (r_showsurfaces.integer == 3)
7780 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7781 else if (r_glsl.integer && gl_support_fragment_shader)
7782 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7783 else if (gl_combine.integer && r_textureunits.integer >= 2)
7784 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7786 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7790 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7793 int texturenumsurfaces, endsurface;
7795 const msurface_t *surface;
7796 const msurface_t *texturesurfacelist[1024];
7798 // if the model is static it doesn't matter what value we give for
7799 // wantnormals and wanttangents, so this logic uses only rules applicable
7800 // to a model, knowing that they are meaningless otherwise
7801 if (ent == r_refdef.scene.worldentity)
7802 RSurf_ActiveWorldEntity();
7803 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7804 RSurf_ActiveModelEntity(ent, false, false);
7806 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7808 for (i = 0;i < numsurfaces;i = j)
7811 surface = rsurface.modelsurfaces + surfacelist[i];
7812 texture = surface->texture;
7813 rsurface.texture = R_GetCurrentTexture(texture);
7814 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7815 // scan ahead until we find a different texture
7816 endsurface = min(i + 1024, numsurfaces);
7817 texturenumsurfaces = 0;
7818 texturesurfacelist[texturenumsurfaces++] = surface;
7819 for (;j < endsurface;j++)
7821 surface = rsurface.modelsurfaces + surfacelist[j];
7822 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7824 texturesurfacelist[texturenumsurfaces++] = surface;
7826 // render the range of surfaces
7827 if (ent == r_refdef.scene.worldentity)
7828 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7830 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7832 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7833 GL_AlphaTest(false);
7836 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7838 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7842 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7844 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7846 RSurf_SetupDepthAndCulling();
7847 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7848 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7850 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7852 RSurf_SetupDepthAndCulling();
7853 GL_AlphaTest(false);
7854 R_Mesh_ColorPointer(NULL, 0, 0);
7855 R_Mesh_ResetTextureState();
7856 R_SetupGenericShader(false);
7857 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7859 GL_BlendFunc(GL_ONE, GL_ZERO);
7860 GL_Color(0, 0, 0, 1);
7861 GL_DepthTest(writedepth);
7862 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7864 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7866 RSurf_SetupDepthAndCulling();
7867 GL_AlphaTest(false);
7868 R_Mesh_ColorPointer(NULL, 0, 0);
7869 R_Mesh_ResetTextureState();
7870 R_SetupGenericShader(false);
7871 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7873 GL_BlendFunc(GL_ONE, GL_ZERO);
7875 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7877 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7878 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7879 else if (!rsurface.texture->currentnumlayers)
7881 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7883 // transparent surfaces get pushed off into the transparent queue
7884 int surfacelistindex;
7885 const msurface_t *surface;
7886 vec3_t tempcenter, center;
7887 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7889 surface = texturesurfacelist[surfacelistindex];
7890 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7891 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7892 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7893 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7894 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7899 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7900 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7905 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7909 // break the surface list down into batches by texture and use of lightmapping
7910 for (i = 0;i < numsurfaces;i = j)
7913 // texture is the base texture pointer, rsurface.texture is the
7914 // current frame/skin the texture is directing us to use (for example
7915 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7916 // use skin 1 instead)
7917 texture = surfacelist[i]->texture;
7918 rsurface.texture = R_GetCurrentTexture(texture);
7919 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7920 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7922 // if this texture is not the kind we want, skip ahead to the next one
7923 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7927 // simply scan ahead until we find a different texture or lightmap state
7928 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7930 // render the range of surfaces
7931 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7935 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7940 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7942 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7944 RSurf_SetupDepthAndCulling();
7945 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7946 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7948 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7950 RSurf_SetupDepthAndCulling();
7951 GL_AlphaTest(false);
7952 R_Mesh_ColorPointer(NULL, 0, 0);
7953 R_Mesh_ResetTextureState();
7954 R_SetupGenericShader(false);
7955 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7957 GL_BlendFunc(GL_ONE, GL_ZERO);
7958 GL_Color(0, 0, 0, 1);
7959 GL_DepthTest(writedepth);
7960 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7962 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7964 RSurf_SetupDepthAndCulling();
7965 GL_AlphaTest(false);
7966 R_Mesh_ColorPointer(NULL, 0, 0);
7967 R_Mesh_ResetTextureState();
7968 R_SetupGenericShader(false);
7969 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7971 GL_BlendFunc(GL_ONE, GL_ZERO);
7973 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7975 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7976 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7977 else if (!rsurface.texture->currentnumlayers)
7979 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7981 // transparent surfaces get pushed off into the transparent queue
7982 int surfacelistindex;
7983 const msurface_t *surface;
7984 vec3_t tempcenter, center;
7985 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7987 surface = texturesurfacelist[surfacelistindex];
7988 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7989 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7990 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7991 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7992 if (queueentity->transparent_offset) // transparent offset
7994 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
7995 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
7996 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
7998 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8003 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8004 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8009 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8013 // break the surface list down into batches by texture and use of lightmapping
8014 for (i = 0;i < numsurfaces;i = j)
8017 // texture is the base texture pointer, rsurface.texture is the
8018 // current frame/skin the texture is directing us to use (for example
8019 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8020 // use skin 1 instead)
8021 texture = surfacelist[i]->texture;
8022 rsurface.texture = R_GetCurrentTexture(texture);
8023 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8024 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8026 // if this texture is not the kind we want, skip ahead to the next one
8027 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8031 // simply scan ahead until we find a different texture or lightmap state
8032 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8034 // render the range of surfaces
8035 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8039 float locboxvertex3f[6*4*3] =
8041 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8042 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8043 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8044 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8045 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8046 1,0,0, 0,0,0, 0,1,0, 1,1,0
8049 unsigned short locboxelements[6*2*3] =
8059 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8062 cl_locnode_t *loc = (cl_locnode_t *)ent;
8064 float vertex3f[6*4*3];
8066 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8067 GL_DepthMask(false);
8068 GL_DepthRange(0, 1);
8069 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8071 GL_CullFace(GL_NONE);
8072 R_Mesh_Matrix(&identitymatrix);
8074 R_Mesh_VertexPointer(vertex3f, 0, 0);
8075 R_Mesh_ColorPointer(NULL, 0, 0);
8076 R_Mesh_ResetTextureState();
8077 R_SetupGenericShader(false);
8080 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8081 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8082 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8083 surfacelist[0] < 0 ? 0.5f : 0.125f);
8085 if (VectorCompare(loc->mins, loc->maxs))
8087 VectorSet(size, 2, 2, 2);
8088 VectorMA(loc->mins, -0.5f, size, mins);
8092 VectorCopy(loc->mins, mins);
8093 VectorSubtract(loc->maxs, loc->mins, size);
8096 for (i = 0;i < 6*4*3;)
8097 for (j = 0;j < 3;j++, i++)
8098 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8100 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8103 void R_DrawLocs(void)
8106 cl_locnode_t *loc, *nearestloc;
8108 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8109 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8111 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8112 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8116 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8118 if (decalsystem->decals)
8119 Mem_Free(decalsystem->decals);
8120 memset(decalsystem, 0, sizeof(*decalsystem));
8123 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)
8132 // expand or initialize the system
8133 if (decalsystem->maxdecals <= decalsystem->numdecals)
8135 decalsystem_t old = *decalsystem;
8136 qboolean useshortelements;
8137 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8138 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8139 decalsystem->decals = Mem_Alloc(r_main_mempool, 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));
8140 decalsystem->vertex3f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8141 decalsystem->texcoord2f = (float *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8142 decalsystem->color4f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8143 decalsystem->element3i = (int *)(decalsystem->color4f + decalsystem->maxdecals*12);
8144 decalsystem->element3s = useshortelements ? (unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3) : NULL;
8145 if (decalsystem->numdecals)
8147 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8148 memcpy(decalsystem->vertex3f, old.vertex3f, decalsystem->numdecals * sizeof(float[3][3]));
8149 memcpy(decalsystem->texcoord2f, old.texcoord2f, decalsystem->numdecals * sizeof(float[3][2]));
8150 memcpy(decalsystem->color4f, old.color4f, decalsystem->numdecals * sizeof(float[3][4]));
8152 for (i = 0;i < decalsystem->maxdecals*3;i++)
8153 decalsystem->element3i[i] = i;
8154 if (useshortelements)
8155 for (i = 0;i < decalsystem->maxdecals*3;i++)
8156 decalsystem->element3s[i] = i;
8159 // grab a decal and search for another free slot for the next one
8160 maxdecals = decalsystem->maxdecals;
8161 decals = decalsystem->decals;
8162 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8163 v3f = decalsystem->vertex3f + 9*i;
8164 tc2f = decalsystem->texcoord2f + 6*i;
8165 for (i = decalsystem->freedecal;i < maxdecals && decals[i].alpha;i++)
8167 decalsystem->freedecal = i;
8168 if (decalsystem->numdecals <= i)
8169 decalsystem->numdecals = i + 1;
8171 // initialize the decal
8172 decal->fade = cl_decals_time.value;
8173 decal->alpha = 1.0f;
8174 decal->colors[0][0] = (unsigned char)(c0[0]*255.0f);
8175 decal->colors[0][1] = (unsigned char)(c0[1]*255.0f);
8176 decal->colors[0][2] = (unsigned char)(c0[2]*255.0f);
8177 decal->colors[0][3] = (unsigned char)(c0[3]*255.0f);
8178 decal->colors[1][0] = (unsigned char)(c1[0]*255.0f);
8179 decal->colors[1][1] = (unsigned char)(c1[1]*255.0f);
8180 decal->colors[1][2] = (unsigned char)(c1[2]*255.0f);
8181 decal->colors[1][3] = (unsigned char)(c1[3]*255.0f);
8182 decal->colors[2][0] = (unsigned char)(c2[0]*255.0f);
8183 decal->colors[2][1] = (unsigned char)(c2[1]*255.0f);
8184 decal->colors[2][2] = (unsigned char)(c2[2]*255.0f);
8185 decal->colors[2][3] = (unsigned char)(c2[3]*255.0f);
8203 void R_DecalSystem_Splat(decalsystem_t *decalsystem, int numvertices, const float *vertex3f, int numtriangles, const int *element3i, const matrix4x4_t *projection, float r, float g, float b, float a, qboolean dynamic)
8212 float tc[9][3]; // third coord is distance fade
8219 float points[2][9][3];
8220 temp = Mem_Alloc(tempmempool, numvertices * sizeof(float[3]));
8221 for (vertexindex = 0;vertexindex < numvertices;vertexindex++)
8222 Matrix4x4_Transform(projection, vertex3f + 3*vertexindex, temp + 3*vertexindex);
8223 for (triangleindex = 0, e = element3i;triangleindex < numtriangles;triangleindex++, e += 3)
8225 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8227 index = 3*e[cornerindex];
8228 VectorCopy(temp + index, tc[cornerindex]);
8230 // cull triangles that are entirely outside the projection
8231 if (min(tc[0][0], min(tc[1][0], tc[2][0])) >= 1)
8233 if (min(tc[0][1], min(tc[1][1], tc[2][1])) >= 1)
8235 if (min(tc[0][2], min(tc[1][2], tc[2][2])) >= 1)
8237 if (max(tc[0][0], max(tc[1][0], tc[2][0])) <= -1)
8239 if (max(tc[0][1], max(tc[1][1], tc[2][1])) <= -1)
8241 if (max(tc[0][2], max(tc[1][2], tc[2][2])) <= -1)
8244 TriangleNormal(tc[0], tc[1], tc[2], normal);
8247 // we accept this triangle
8248 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8250 index = 3*e[cornerindex];
8251 VectorCopy(vertex3f + index, v[cornerindex]);
8252 // calculate distance fade from the projection origin
8253 f = a * (1-fabs(tc[cornerindex][2]));
8254 c[cornerindex][0] = r * f;
8255 c[cornerindex][1] = g * f;
8256 c[cornerindex][2] = b * f;
8257 c[cornerindex][3] = 1;
8261 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex);
8265 // clip by each of the box planes formed from the projection matrix
8266 Matrix4x4_ToVectors(projection, planes[0], planes[2], planes[4], origin);
8267 VectorNegate(planes[0], planes[1]);
8268 VectorNegate(planes[2], planes[3]);
8269 VectorNegate(planes[4], planes[5]);
8270 VectorCopy(planes[4], normal);
8271 VectorNormalize(normal);
8272 VectorMA(v[0], 0.125f, planes[4], v[0]);
8273 VectorMA(v[1], 0.125f, planes[4], v[1]);
8274 VectorMA(v[2], 0.125f, planes[4], v[2]);
8275 numpoints = PolygonF_Clip(3 , v[0] , planes[0][0], planes[0][1], planes[0][2], DotProduct(planes[0], origin) - 1, 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
8276 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], DotProduct(planes[1], origin) - 1, 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
8277 numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], DotProduct(planes[2], origin) - 1, 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
8278 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], DotProduct(planes[3], origin) - 1, 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
8279 numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], DotProduct(planes[4], origin) - 1, 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
8280 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], DotProduct(planes[5], origin) - 1, 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
8281 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8283 // convert vertex positions to texcoords
8284 Matrix4x4_Transform(projection, v[cornerindex], tc[cornerindex]);
8285 // calculate distance fade from the projection origin
8286 f = a * (1-fabs(tc[cornerindex][2]));
8287 c[cornerindex][0] = r * f;
8288 c[cornerindex][1] = g * f;
8289 c[cornerindex][2] = b * f;
8290 c[cornerindex][3] = 1;
8292 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8293 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);
8298 extern skinframe_t *decalskinframe;
8299 void RSurf_DrawTriDecals(void)
8302 decalsystem_t *decalsystem = &rsurface.entity->decalsystem;
8303 int numdecals = decalsystem->numdecals;
8304 tridecal_t *decal = decalsystem->decals;
8305 float frametime = cl.time - decalsystem->lastupdatetime;
8313 decalsystem->lastupdatetime = cl.time;
8315 if (!decalsystem->numdecals)
8318 decalfade = 1.0f / max(0.001f, cl_decals_fadetime.value);
8319 alphascale = (1.0f / 255.0f);
8321 if (rsurface.ent_color[3] < 1 || (rsurface.ent_flags & RENDER_ADDITIVE))
8323 Mem_Free(decalsystem->decals);
8324 memset(decalsystem, 0, sizeof(*decalsystem));
8331 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8336 decal->fade -= frametime;
8337 if (decal->fade <= 0)
8339 decal->alpha -= decalfade;
8340 if (decal->alpha <= 0)
8342 // kill the decal by zeroing vertex data
8343 memset(decalsystem->vertex3f + 9*i, 0, sizeof(float[3][3]));
8344 memset(decalsystem->texcoord2f + 6*i, 0, sizeof(float[3][2]));
8345 memset(decalsystem->color4f + 12*i, 0, sizeof(float[3][4]));
8346 memset(decal, 0, sizeof(*decal));
8347 if (decalsystem->freedecal > i)
8348 decalsystem->freedecal = i;
8353 // update color values for fading decals
8354 ca = decal->alpha * alphascale;
8355 c4f = decalsystem->color4f + 12*i;
8356 c4f[ 0] = decal->colors[0][0] * ca;
8357 c4f[ 1] = decal->colors[0][1] * ca;
8358 c4f[ 2] = decal->colors[0][2] * ca;
8360 c4f[ 4] = decal->colors[1][0] * ca;
8361 c4f[ 5] = decal->colors[1][1] * ca;
8362 c4f[ 6] = decal->colors[1][2] * ca;
8364 c4f[ 8] = decal->colors[2][0] * ca;
8365 c4f[ 9] = decal->colors[2][1] * ca;
8366 c4f[10] = decal->colors[2][2] * ca;
8369 // update vertex positions for animated models
8370 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8372 e = rsurface.modelelement3i + 3*decal->triangleindex;
8373 v3f = decalsystem->vertex3f + i*i;
8374 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8375 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8376 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8379 r_refdef.stats.decals++;
8382 // reduce numdecals if possible
8383 while (numdecals > 0 && !decalsystem->decals[numdecals - 1].alpha)
8385 decalsystem->numdecals = numdecals;
8389 // now render the decals all at once
8390 // (this assumes they all use one particle font texture!)
8391 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);
8392 R_Mesh_ResetTextureState();
8393 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8394 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8395 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8396 R_SetupGenericShader(true);
8397 GL_DepthMask(false);
8398 GL_DepthRange(0, 1);
8399 GL_PolygonOffset(0, 0);
8401 GL_CullFace(GL_NONE);
8402 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8403 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8404 GL_LockArrays(0, numdecals * 3);
8405 R_Mesh_Draw(0, numdecals * 3, 0, numdecals, decalsystem->element3i, decalsystem->element3s, 0, 0);
8406 GL_LockArrays(0, 0);
8410 // if there are no decals left, reset decalsystem
8411 R_DecalSystem_Reset(decalsystem);
8415 void R_DrawDebugModel(void)
8417 entity_render_t *ent = rsurface.entity;
8418 int i, j, k, l, flagsmask;
8419 const int *elements;
8421 const msurface_t *surface;
8422 dp_model_t *model = ent->model;
8425 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8427 R_Mesh_ColorPointer(NULL, 0, 0);
8428 R_Mesh_ResetTextureState();
8429 R_SetupGenericShader(false);
8430 GL_DepthRange(0, 1);
8431 GL_DepthTest(!r_showdisabledepthtest.integer);
8432 GL_DepthMask(false);
8433 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8435 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8437 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8438 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8440 if (brush->colbrushf && brush->colbrushf->numtriangles)
8442 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8443 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);
8444 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8447 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8449 if (surface->num_collisiontriangles)
8451 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8452 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);
8453 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8458 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8460 if (r_showtris.integer || r_shownormals.integer)
8462 if (r_showdisabledepthtest.integer)
8464 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8465 GL_DepthMask(false);
8469 GL_BlendFunc(GL_ONE, GL_ZERO);
8472 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8474 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8476 rsurface.texture = R_GetCurrentTexture(surface->texture);
8477 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8479 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8480 if (r_showtris.value > 0)
8482 if (!rsurface.texture->currentlayers->depthmask)
8483 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8484 else if (ent == r_refdef.scene.worldentity)
8485 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8487 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8488 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8489 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8490 R_Mesh_ColorPointer(NULL, 0, 0);
8491 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8492 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8493 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8494 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);
8495 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8498 if (r_shownormals.value < 0)
8501 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8503 VectorCopy(rsurface.vertex3f + l * 3, v);
8504 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8505 qglVertex3f(v[0], v[1], v[2]);
8506 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8507 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8508 qglVertex3f(v[0], v[1], v[2]);
8513 if (r_shownormals.value > 0)
8516 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8518 VectorCopy(rsurface.vertex3f + l * 3, v);
8519 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8520 qglVertex3f(v[0], v[1], v[2]);
8521 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8522 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8523 qglVertex3f(v[0], v[1], v[2]);
8528 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8530 VectorCopy(rsurface.vertex3f + l * 3, v);
8531 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8532 qglVertex3f(v[0], v[1], v[2]);
8533 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8534 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8535 qglVertex3f(v[0], v[1], v[2]);
8540 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8542 VectorCopy(rsurface.vertex3f + l * 3, v);
8543 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8544 qglVertex3f(v[0], v[1], v[2]);
8545 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8546 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8547 qglVertex3f(v[0], v[1], v[2]);
8554 rsurface.texture = NULL;
8558 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8559 int r_maxsurfacelist = 0;
8560 const msurface_t **r_surfacelist = NULL;
8561 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8563 int i, j, endj, f, flagsmask;
8565 dp_model_t *model = r_refdef.scene.worldmodel;
8566 msurface_t *surfaces;
8567 unsigned char *update;
8568 int numsurfacelist = 0;
8572 if (r_maxsurfacelist < model->num_surfaces)
8574 r_maxsurfacelist = model->num_surfaces;
8576 Mem_Free(r_surfacelist);
8577 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8580 RSurf_ActiveWorldEntity();
8582 surfaces = model->data_surfaces;
8583 update = model->brushq1.lightmapupdateflags;
8585 // update light styles on this submodel
8586 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8588 model_brush_lightstyleinfo_t *style;
8589 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8591 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8593 int *list = style->surfacelist;
8594 style->value = r_refdef.scene.lightstylevalue[style->style];
8595 for (j = 0;j < style->numsurfaces;j++)
8596 update[list[j]] = true;
8601 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8606 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8612 rsurface.uselightmaptexture = false;
8613 rsurface.texture = NULL;
8614 rsurface.rtlight = NULL;
8616 // add visible surfaces to draw list
8617 for (i = 0;i < model->nummodelsurfaces;i++)
8619 j = model->sortedmodelsurfaces[i];
8620 if (r_refdef.viewcache.world_surfacevisible[j])
8621 r_surfacelist[numsurfacelist++] = surfaces + j;
8623 // update lightmaps if needed
8625 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8626 if (r_refdef.viewcache.world_surfacevisible[j])
8628 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8629 // don't do anything if there were no surfaces
8630 if (!numsurfacelist)
8632 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8635 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8636 GL_AlphaTest(false);
8638 // add to stats if desired
8639 if (r_speeds.integer && !skysurfaces && !depthonly)
8641 r_refdef.stats.world_surfaces += numsurfacelist;
8642 for (j = 0;j < numsurfacelist;j++)
8643 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8647 RSurf_DrawTriDecals();
8649 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8652 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8654 int i, j, endj, f, flagsmask;
8656 dp_model_t *model = ent->model;
8657 msurface_t *surfaces;
8658 unsigned char *update;
8659 int numsurfacelist = 0;
8663 if (r_maxsurfacelist < model->num_surfaces)
8665 r_maxsurfacelist = model->num_surfaces;
8667 Mem_Free(r_surfacelist);
8668 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8671 // if the model is static it doesn't matter what value we give for
8672 // wantnormals and wanttangents, so this logic uses only rules applicable
8673 // to a model, knowing that they are meaningless otherwise
8674 if (ent == r_refdef.scene.worldentity)
8675 RSurf_ActiveWorldEntity();
8676 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8677 RSurf_ActiveModelEntity(ent, false, false);
8679 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8681 surfaces = model->data_surfaces;
8682 update = model->brushq1.lightmapupdateflags;
8684 // update light styles
8685 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8687 model_brush_lightstyleinfo_t *style;
8688 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8690 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8692 int *list = style->surfacelist;
8693 style->value = r_refdef.scene.lightstylevalue[style->style];
8694 for (j = 0;j < style->numsurfaces;j++)
8695 update[list[j]] = true;
8700 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8705 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8711 rsurface.uselightmaptexture = false;
8712 rsurface.texture = NULL;
8713 rsurface.rtlight = NULL;
8715 // add visible surfaces to draw list
8716 for (i = 0;i < model->nummodelsurfaces;i++)
8717 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8718 // don't do anything if there were no surfaces
8719 if (!numsurfacelist)
8721 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8724 // update lightmaps if needed
8726 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8728 R_BuildLightMap(ent, surfaces + j);
8729 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8730 GL_AlphaTest(false);
8732 // add to stats if desired
8733 if (r_speeds.integer && !skysurfaces && !depthonly)
8735 r_refdef.stats.entities_surfaces += numsurfacelist;
8736 for (j = 0;j < numsurfacelist;j++)
8737 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8741 RSurf_DrawTriDecals();
8743 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8746 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
8748 static texture_t texture;
8749 static msurface_t surface;
8750 const msurface_t *surfacelist = &surface;
8752 // fake enough texture and surface state to render this geometry
8754 texture.update_lastrenderframe = -1; // regenerate this texture
8755 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
8756 texture.currentskinframe = skinframe;
8757 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
8758 texture.specularscalemod = 1;
8759 texture.specularpowermod = 1;
8761 surface.texture = &texture;
8762 surface.num_triangles = numtriangles;
8763 surface.num_firsttriangle = firsttriangle;
8764 surface.num_vertices = numvertices;
8765 surface.num_firstvertex = firstvertex;
8768 rsurface.texture = R_GetCurrentTexture(surface.texture);
8769 rsurface.uselightmaptexture = false;
8770 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);