2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
47 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
48 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
49 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "1", "light equalizing: ensure at least this ambient/diffuse ratio"};
50 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
51 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
53 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
55 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
56 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
57 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
58 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
59 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
60 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
61 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
62 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
63 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
64 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
65 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
66 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
67 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
68 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
69 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
70 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
71 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
72 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
73 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
74 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
75 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
76 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
77 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
78 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
79 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
80 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
81 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
82 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
83 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
84 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
85 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
86 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
87 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
88 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "4", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
89 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
90 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
92 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
93 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
94 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
95 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
96 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
97 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
98 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
99 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
101 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
103 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
104 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
105 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
106 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
107 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
108 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
109 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
110 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
111 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
112 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
113 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
115 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
116 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
117 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
118 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
119 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
121 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
122 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
123 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
124 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
126 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
127 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
128 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
129 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
130 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
131 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
132 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
134 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
135 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
136 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
137 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
139 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
141 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
143 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
145 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
146 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
147 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
148 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
149 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
150 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
151 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
153 extern cvar_t v_glslgamma;
155 extern qboolean v_flipped_state;
157 static struct r_bloomstate_s
162 int bloomwidth, bloomheight;
164 int screentexturewidth, screentextureheight;
165 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
167 int bloomtexturewidth, bloomtextureheight;
168 rtexture_t *texture_bloom;
170 // arrays for rendering the screen passes
171 float screentexcoord2f[8];
172 float bloomtexcoord2f[8];
173 float offsettexcoord2f[8];
175 r_viewport_t viewport;
179 r_waterstate_t r_waterstate;
181 /// shadow volume bsp struct with automatically growing nodes buffer
184 rtexture_t *r_texture_blanknormalmap;
185 rtexture_t *r_texture_white;
186 rtexture_t *r_texture_grey128;
187 rtexture_t *r_texture_black;
188 rtexture_t *r_texture_notexture;
189 rtexture_t *r_texture_whitecube;
190 rtexture_t *r_texture_normalizationcube;
191 rtexture_t *r_texture_fogattenuation;
192 rtexture_t *r_texture_gammaramps;
193 unsigned int r_texture_gammaramps_serial;
194 //rtexture_t *r_texture_fogintensity;
196 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
197 unsigned int r_numqueries;
198 unsigned int r_maxqueries;
200 typedef struct r_qwskincache_s
202 char name[MAX_QPATH];
203 skinframe_t *skinframe;
207 static r_qwskincache_t *r_qwskincache;
208 static int r_qwskincache_size;
210 /// vertex coordinates for a quad that covers the screen exactly
211 const float r_screenvertex3f[12] =
219 extern void R_DrawModelShadows(void);
221 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
224 for (i = 0;i < verts;i++)
235 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
238 for (i = 0;i < verts;i++)
248 // FIXME: move this to client?
251 if (gamemode == GAME_NEHAHRA)
253 Cvar_Set("gl_fogenable", "0");
254 Cvar_Set("gl_fogdensity", "0.2");
255 Cvar_Set("gl_fogred", "0.3");
256 Cvar_Set("gl_foggreen", "0.3");
257 Cvar_Set("gl_fogblue", "0.3");
259 r_refdef.fog_density = 0;
260 r_refdef.fog_red = 0;
261 r_refdef.fog_green = 0;
262 r_refdef.fog_blue = 0;
263 r_refdef.fog_alpha = 1;
264 r_refdef.fog_start = 0;
265 r_refdef.fog_end = 0;
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, 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, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
6109 static float scale[8];
6110 vec3_t worldfogpoint, localfogpoint;
6112 rsurface.entity = r_refdef.scene.worldentity;
6113 rsurface.ent_skinnum = 0;
6114 rsurface.ent_qwskin = -1;
6115 rsurface.ent_shadertime = shadertime;
6116 Vector4Set(rsurface.ent_color, r, g, b, a);
6117 rsurface.ent_flags = entflags;
6118 rsurface.modelnum_vertices = numvertices;
6119 rsurface.modelnum_triangles = numtriangles;
6120 if (rsurface.array_size < rsurface.modelnum_vertices)
6121 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6122 rsurface.matrix = *matrix;
6123 rsurface.inversematrix = *inversematrix;
6124 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6125 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6126 R_Mesh_Matrix(&rsurface.matrix);
6129 scale[1] = rsurface.matrixscale;
6130 scale[2] = rsurface.inversematrixscale;
6131 scale[3] = rsurface.matrixscale * rsurface.matrixscale;
6132 scale[4] = rsurface.inversematrixscale * rsurface.inversematrixscale;
6133 scale[5] = rsurface.matrixscale * rsurface.matrixscale * rsurface.matrixscale;
6134 scale[6] = rsurface.inversematrixscale * rsurface.inversematrixscale * rsurface.inversematrixscale;
6138 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6139 //Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6140 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.fogplane, rsurface.fogplane);
6141 VectorNormalize(rsurface.fogplane);
6142 VectorScale(r_refdef.fogplane, -r_refdef.fogplane[3], worldfogpoint);
6143 Matrix4x4_Transform(&rsurface.inversematrix, worldfogpoint, localfogpoint);
6144 rsurface.fogplane[3] = -DotProduct(rsurface.fogplane, localfogpoint);
6145 rsurface.fogplaneviewdist = DotProduct(rsurface.localvieworigin, rsurface.fogplane) + rsurface.fogplane[3];
6146 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6147 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6148 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6151 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6152 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6153 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6154 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6155 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6156 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6160 if (r_refdef.fogenabled && memcmp(&rsurface.matrix, &identitymatrix, sizeof(rsurface.matrix)))
6162 qboolean fail = false;
6163 vec3_t temp, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
6164 VectorScale(r_refdef.fogplane, r_refdef.fogplane[3], temp);
6165 Matrix4x4_Transform(&rsurface.inversematrix, temp, temp2);
6166 //rsurface.fogplane[3] = -DotProduct(temp2, rsurface.fogplane);
6167 //rsurface.fogplaneviewdist = DotProduct(rsurface.localvieworigin, rsurface.fogplane) + rsurface.fogplane[3];
6168 VectorScale(rsurface.fogplane, rsurface.fogplane[3], temp3);
6169 Matrix4x4_Transform(&rsurface.matrix, temp3, temp4);
6170 VectorSet(temp5, r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2] + 1000);
6171 Matrix4x4_Transform(&rsurface.inversematrix, temp5, temp6);
6172 VectorSet(temp7, r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2] - 1000);
6173 Matrix4x4_Transform(&rsurface.inversematrix, temp7, temp8);
6174 Con_Printf("#%i : %f %f %f %f : %f %f %f : %f %f %f : %f %f\n", r_test.integer,
6175 rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3],
6176 rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2],
6177 rsurface.fogplaneviewdist,
6178 DotProduct(rsurface.localvieworigin, rsurface.fogplane) - DotProduct(temp2, rsurface.fogplane),
6179 DotProduct(r_refdef.view.origin, r_refdef.fogplane) + r_refdef.fogplane[3],
6180 rsurface.fogplane[3] - -DotProduct(temp2, rsurface.fogplane),
6181 r_refdef.fogplane[3] - -DotProduct(temp4, r_refdef.fogplane)
6183 //if (fabs(RSurf_FogVertex(temp6) - RSurf_FogPoint(temp5)) > 0.1)
6185 //if (fabs(RSurf_FogVertex(temp8) - RSurf_FogPoint(temp7)) > 0.1)
6187 //if (fabs(rsurface.fogplaneviewdist * rsurface.matrixscale - r_refdef.fogplaneviewdist) > 1)
6189 //if (fabs((DotProduct(rsurface.localvieworigin, rsurface.fogplane) + rsurface.fogplane[3]) * rsurface.matrixscale - r_refdef.fogplaneviewdist) > 1)
6191 //if (fabs(-DotProduct(temp2, rsurface.fogplane) - rsurface.fogplane[3]) > 1)
6193 //if (fabs(-DotProduct(temp4, r_refdef.fogplane) - r_refdef.fogplane[3]) > 1)
6195 //if (fabs(rsurface.fogplaneviewdist - DotProduct(rsurface.localvieworigin, rsurface.fogplane) - rsurface.fogplane[3]) > 1)
6197 //if (fabs(DotProduct(rsurface.localvieworigin, rsurface.fogplane) - DotProduct(temp2, rsurface.fogplane) - rsurface.fogplaneviewdist) > 1)
6200 Cvar_SetValueQuick(&r_test, r_test.integer + 1);
6204 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6205 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6206 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6207 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6208 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6209 VectorSet(rsurface.glowmod, 1, 1, 1);
6210 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6211 rsurface.frameblend[0].lerp = 1;
6212 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6213 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6216 rsurface.modelvertex3f = vertex3f;
6217 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6218 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6219 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6221 else if (wantnormals)
6223 rsurface.modelvertex3f = vertex3f;
6224 rsurface.modelsvector3f = NULL;
6225 rsurface.modeltvector3f = NULL;
6226 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6230 rsurface.modelvertex3f = vertex3f;
6231 rsurface.modelsvector3f = NULL;
6232 rsurface.modeltvector3f = NULL;
6233 rsurface.modelnormal3f = NULL;
6235 rsurface.modelvertex3f_bufferobject = 0;
6236 rsurface.modelvertex3f_bufferoffset = 0;
6237 rsurface.modelsvector3f_bufferobject = 0;
6238 rsurface.modelsvector3f_bufferoffset = 0;
6239 rsurface.modeltvector3f_bufferobject = 0;
6240 rsurface.modeltvector3f_bufferoffset = 0;
6241 rsurface.modelnormal3f_bufferobject = 0;
6242 rsurface.modelnormal3f_bufferoffset = 0;
6243 rsurface.generatedvertex = true;
6244 rsurface.modellightmapcolor4f = NULL;
6245 rsurface.modellightmapcolor4f_bufferobject = 0;
6246 rsurface.modellightmapcolor4f_bufferoffset = 0;
6247 rsurface.modeltexcoordtexture2f = texcoord2f;
6248 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6249 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6250 rsurface.modeltexcoordlightmap2f = NULL;
6251 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6252 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6253 rsurface.modelelement3i = element3i;
6254 rsurface.modelelement3s = element3s;
6255 rsurface.modelelement3i_bufferobject = 0;
6256 rsurface.modelelement3s_bufferobject = 0;
6257 rsurface.modellightmapoffsets = NULL;
6258 rsurface.modelsurfaces = NULL;
6259 rsurface.vertex3f = rsurface.modelvertex3f;
6260 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6261 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6262 rsurface.svector3f = rsurface.modelsvector3f;
6263 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6264 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6265 rsurface.tvector3f = rsurface.modeltvector3f;
6266 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6267 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6268 rsurface.normal3f = rsurface.modelnormal3f;
6269 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6270 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6271 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6273 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6275 if ((wantnormals || wanttangents) && !normal3f)
6276 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6277 if (wanttangents && !svector3f)
6278 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);
6282 float RSurf_FogPoint(const float *v)
6284 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6285 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6286 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6287 float FogHeightFade = r_refdef.fogheightfade;
6289 unsigned int fogmasktableindex;
6290 if (r_refdef.fogplaneviewabove)
6291 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6293 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6294 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6295 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6298 float RSurf_FogVertex(const float *v)
6300 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6301 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6302 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6303 float FogHeightFade = rsurface.fogheightfade;
6305 unsigned int fogmasktableindex;
6306 if (r_refdef.fogplaneviewabove)
6307 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6309 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6310 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6311 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6314 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6315 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6318 int texturesurfaceindex;
6323 const float *v1, *in_tc;
6325 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6327 q3shaderinfo_deform_t *deform;
6328 // 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
6329 if (rsurface.generatedvertex)
6331 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6332 generatenormals = true;
6333 for (i = 0;i < Q3MAXDEFORMS;i++)
6335 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6337 generatetangents = true;
6338 generatenormals = true;
6340 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6341 generatenormals = true;
6343 if (generatenormals && !rsurface.modelnormal3f)
6345 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6346 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6347 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6348 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6350 if (generatetangents && !rsurface.modelsvector3f)
6352 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6353 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6354 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6355 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6356 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6357 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6358 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);
6361 rsurface.vertex3f = rsurface.modelvertex3f;
6362 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6363 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6364 rsurface.svector3f = rsurface.modelsvector3f;
6365 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6366 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6367 rsurface.tvector3f = rsurface.modeltvector3f;
6368 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6369 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6370 rsurface.normal3f = rsurface.modelnormal3f;
6371 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6372 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6373 // if vertices are deformed (sprite flares and things in maps, possibly
6374 // water waves, bulges and other deformations), generate them into
6375 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6376 // (may be static model data or generated data for an animated model, or
6377 // the previous deform pass)
6378 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6380 switch (deform->deform)
6383 case Q3DEFORM_PROJECTIONSHADOW:
6384 case Q3DEFORM_TEXT0:
6385 case Q3DEFORM_TEXT1:
6386 case Q3DEFORM_TEXT2:
6387 case Q3DEFORM_TEXT3:
6388 case Q3DEFORM_TEXT4:
6389 case Q3DEFORM_TEXT5:
6390 case Q3DEFORM_TEXT6:
6391 case Q3DEFORM_TEXT7:
6394 case Q3DEFORM_AUTOSPRITE:
6395 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6396 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6397 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6398 VectorNormalize(newforward);
6399 VectorNormalize(newright);
6400 VectorNormalize(newup);
6401 // make deformed versions of only the model vertices used by the specified surfaces
6402 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6404 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6405 // a single autosprite surface can contain multiple sprites...
6406 for (j = 0;j < surface->num_vertices - 3;j += 4)
6408 VectorClear(center);
6409 for (i = 0;i < 4;i++)
6410 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6411 VectorScale(center, 0.25f, center);
6412 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6413 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6414 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6415 for (i = 0;i < 4;i++)
6417 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6418 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6421 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);
6422 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);
6424 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6425 rsurface.vertex3f_bufferobject = 0;
6426 rsurface.vertex3f_bufferoffset = 0;
6427 rsurface.svector3f = rsurface.array_deformedsvector3f;
6428 rsurface.svector3f_bufferobject = 0;
6429 rsurface.svector3f_bufferoffset = 0;
6430 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6431 rsurface.tvector3f_bufferobject = 0;
6432 rsurface.tvector3f_bufferoffset = 0;
6433 rsurface.normal3f = rsurface.array_deformednormal3f;
6434 rsurface.normal3f_bufferobject = 0;
6435 rsurface.normal3f_bufferoffset = 0;
6437 case Q3DEFORM_AUTOSPRITE2:
6438 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6439 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6440 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6441 VectorNormalize(newforward);
6442 VectorNormalize(newright);
6443 VectorNormalize(newup);
6444 // make deformed versions of only the model vertices used by the specified surfaces
6445 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6447 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6448 const float *v1, *v2;
6458 memset(shortest, 0, sizeof(shortest));
6459 // a single autosprite surface can contain multiple sprites...
6460 for (j = 0;j < surface->num_vertices - 3;j += 4)
6462 VectorClear(center);
6463 for (i = 0;i < 4;i++)
6464 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6465 VectorScale(center, 0.25f, center);
6466 // find the two shortest edges, then use them to define the
6467 // axis vectors for rotating around the central axis
6468 for (i = 0;i < 6;i++)
6470 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6471 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6473 Debug_PolygonBegin(NULL, 0);
6474 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6475 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);
6476 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6479 l = VectorDistance2(v1, v2);
6480 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6482 l += (1.0f / 1024.0f);
6483 if (shortest[0].length2 > l || i == 0)
6485 shortest[1] = shortest[0];
6486 shortest[0].length2 = l;
6487 shortest[0].v1 = v1;
6488 shortest[0].v2 = v2;
6490 else if (shortest[1].length2 > l || i == 1)
6492 shortest[1].length2 = l;
6493 shortest[1].v1 = v1;
6494 shortest[1].v2 = v2;
6497 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6498 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6500 Debug_PolygonBegin(NULL, 0);
6501 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6502 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);
6503 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6506 // this calculates the right vector from the shortest edge
6507 // and the up vector from the edge midpoints
6508 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6509 VectorNormalize(right);
6510 VectorSubtract(end, start, up);
6511 VectorNormalize(up);
6512 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6513 VectorSubtract(rsurface.localvieworigin, center, forward);
6514 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6515 VectorNegate(forward, forward);
6516 VectorReflect(forward, 0, up, forward);
6517 VectorNormalize(forward);
6518 CrossProduct(up, forward, newright);
6519 VectorNormalize(newright);
6521 Debug_PolygonBegin(NULL, 0);
6522 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);
6523 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6524 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6528 Debug_PolygonBegin(NULL, 0);
6529 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6530 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6531 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6534 // rotate the quad around the up axis vector, this is made
6535 // especially easy by the fact we know the quad is flat,
6536 // so we only have to subtract the center position and
6537 // measure distance along the right vector, and then
6538 // multiply that by the newright vector and add back the
6540 // we also need to subtract the old position to undo the
6541 // displacement from the center, which we do with a
6542 // DotProduct, the subtraction/addition of center is also
6543 // optimized into DotProducts here
6544 l = DotProduct(right, center);
6545 for (i = 0;i < 4;i++)
6547 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6548 f = DotProduct(right, v1) - l;
6549 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6552 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);
6553 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);
6555 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6556 rsurface.vertex3f_bufferobject = 0;
6557 rsurface.vertex3f_bufferoffset = 0;
6558 rsurface.svector3f = rsurface.array_deformedsvector3f;
6559 rsurface.svector3f_bufferobject = 0;
6560 rsurface.svector3f_bufferoffset = 0;
6561 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6562 rsurface.tvector3f_bufferobject = 0;
6563 rsurface.tvector3f_bufferoffset = 0;
6564 rsurface.normal3f = rsurface.array_deformednormal3f;
6565 rsurface.normal3f_bufferobject = 0;
6566 rsurface.normal3f_bufferoffset = 0;
6568 case Q3DEFORM_NORMAL:
6569 // deform the normals to make reflections wavey
6570 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6572 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6573 for (j = 0;j < surface->num_vertices;j++)
6576 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6577 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6578 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6579 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6580 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6581 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6582 VectorNormalize(normal);
6584 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);
6586 rsurface.svector3f = rsurface.array_deformedsvector3f;
6587 rsurface.svector3f_bufferobject = 0;
6588 rsurface.svector3f_bufferoffset = 0;
6589 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6590 rsurface.tvector3f_bufferobject = 0;
6591 rsurface.tvector3f_bufferoffset = 0;
6592 rsurface.normal3f = rsurface.array_deformednormal3f;
6593 rsurface.normal3f_bufferobject = 0;
6594 rsurface.normal3f_bufferoffset = 0;
6597 // deform vertex array to make wavey water and flags and such
6598 waveparms[0] = deform->waveparms[0];
6599 waveparms[1] = deform->waveparms[1];
6600 waveparms[2] = deform->waveparms[2];
6601 waveparms[3] = deform->waveparms[3];
6602 // this is how a divisor of vertex influence on deformation
6603 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6604 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6605 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6607 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6608 for (j = 0;j < surface->num_vertices;j++)
6610 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6611 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6612 // if the wavefunc depends on time, evaluate it per-vertex
6615 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6616 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6618 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6621 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6622 rsurface.vertex3f_bufferobject = 0;
6623 rsurface.vertex3f_bufferoffset = 0;
6625 case Q3DEFORM_BULGE:
6626 // deform vertex array to make the surface have moving bulges
6627 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6629 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6630 for (j = 0;j < surface->num_vertices;j++)
6632 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6633 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6636 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6637 rsurface.vertex3f_bufferobject = 0;
6638 rsurface.vertex3f_bufferoffset = 0;
6641 // deform vertex array
6642 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6643 VectorScale(deform->parms, scale, waveparms);
6644 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6646 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6647 for (j = 0;j < surface->num_vertices;j++)
6648 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6650 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6651 rsurface.vertex3f_bufferobject = 0;
6652 rsurface.vertex3f_bufferoffset = 0;
6656 // generate texcoords based on the chosen texcoord source
6657 switch(rsurface.texture->tcgen.tcgen)
6660 case Q3TCGEN_TEXTURE:
6661 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6662 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6663 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6665 case Q3TCGEN_LIGHTMAP:
6666 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6667 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6668 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6670 case Q3TCGEN_VECTOR:
6671 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6673 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6674 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)
6676 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6677 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6680 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6681 rsurface.texcoordtexture2f_bufferobject = 0;
6682 rsurface.texcoordtexture2f_bufferoffset = 0;
6684 case Q3TCGEN_ENVIRONMENT:
6685 // make environment reflections using a spheremap
6686 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6688 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6689 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6690 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6691 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6692 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6694 // identical to Q3A's method, but executed in worldspace so
6695 // carried models can be shiny too
6697 float viewer[3], d, reflected[3], worldreflected[3];
6699 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6700 // VectorNormalize(viewer);
6702 d = DotProduct(normal, viewer);
6704 reflected[0] = normal[0]*2*d - viewer[0];
6705 reflected[1] = normal[1]*2*d - viewer[1];
6706 reflected[2] = normal[2]*2*d - viewer[2];
6707 // note: this is proportinal to viewer, so we can normalize later
6709 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6710 VectorNormalize(worldreflected);
6712 // note: this sphere map only uses world x and z!
6713 // so positive and negative y will LOOK THE SAME.
6714 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6715 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6718 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6719 rsurface.texcoordtexture2f_bufferobject = 0;
6720 rsurface.texcoordtexture2f_bufferoffset = 0;
6723 // the only tcmod that needs software vertex processing is turbulent, so
6724 // check for it here and apply the changes if needed
6725 // and we only support that as the first one
6726 // (handling a mixture of turbulent and other tcmods would be problematic
6727 // without punting it entirely to a software path)
6728 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6730 amplitude = rsurface.texture->tcmods[0].parms[1];
6731 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6732 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6734 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6735 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)
6737 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6738 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6741 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6742 rsurface.texcoordtexture2f_bufferobject = 0;
6743 rsurface.texcoordtexture2f_bufferoffset = 0;
6745 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6746 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6747 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6748 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6751 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6754 const msurface_t *surface = texturesurfacelist[0];
6755 const msurface_t *surface2;
6760 // TODO: lock all array ranges before render, rather than on each surface
6761 if (texturenumsurfaces == 1)
6763 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6764 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);
6766 else if (r_batchmode.integer == 2)
6768 #define MAXBATCHTRIANGLES 4096
6769 int batchtriangles = 0;
6770 int batchelements[MAXBATCHTRIANGLES*3];
6771 for (i = 0;i < texturenumsurfaces;i = j)
6773 surface = texturesurfacelist[i];
6775 if (surface->num_triangles > MAXBATCHTRIANGLES)
6777 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);
6780 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6781 batchtriangles = surface->num_triangles;
6782 firstvertex = surface->num_firstvertex;
6783 endvertex = surface->num_firstvertex + surface->num_vertices;
6784 for (;j < texturenumsurfaces;j++)
6786 surface2 = texturesurfacelist[j];
6787 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6789 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6790 batchtriangles += surface2->num_triangles;
6791 firstvertex = min(firstvertex, surface2->num_firstvertex);
6792 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6794 surface2 = texturesurfacelist[j-1];
6795 numvertices = endvertex - firstvertex;
6796 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6799 else if (r_batchmode.integer == 1)
6801 for (i = 0;i < texturenumsurfaces;i = j)
6803 surface = texturesurfacelist[i];
6804 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6805 if (texturesurfacelist[j] != surface2)
6807 surface2 = texturesurfacelist[j-1];
6808 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6809 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6810 GL_LockArrays(surface->num_firstvertex, numvertices);
6811 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6816 for (i = 0;i < texturenumsurfaces;i++)
6818 surface = texturesurfacelist[i];
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);
6825 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6827 int i, planeindex, vertexindex;
6831 r_waterstate_waterplane_t *p, *bestp;
6832 const msurface_t *surface;
6833 if (r_waterstate.renderingscene)
6835 for (i = 0;i < texturenumsurfaces;i++)
6837 surface = texturesurfacelist[i];
6838 if (lightmaptexunit >= 0)
6839 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6840 if (deluxemaptexunit >= 0)
6841 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6842 // pick the closest matching water plane
6845 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6848 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6850 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6851 d += fabs(PlaneDiff(vert, &p->plane));
6853 if (bestd > d || !bestp)
6861 if (refractiontexunit >= 0)
6862 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6863 if (reflectiontexunit >= 0)
6864 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6868 if (refractiontexunit >= 0)
6869 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6870 if (reflectiontexunit >= 0)
6871 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6873 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6874 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6878 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6882 const msurface_t *surface = texturesurfacelist[0];
6883 const msurface_t *surface2;
6888 // TODO: lock all array ranges before render, rather than on each surface
6889 if (texturenumsurfaces == 1)
6891 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6892 if (deluxemaptexunit >= 0)
6893 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6894 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6895 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);
6897 else if (r_batchmode.integer == 2)
6899 #define MAXBATCHTRIANGLES 4096
6900 int batchtriangles = 0;
6901 int batchelements[MAXBATCHTRIANGLES*3];
6902 for (i = 0;i < texturenumsurfaces;i = j)
6904 surface = texturesurfacelist[i];
6905 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6906 if (deluxemaptexunit >= 0)
6907 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6909 if (surface->num_triangles > MAXBATCHTRIANGLES)
6911 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);
6914 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6915 batchtriangles = surface->num_triangles;
6916 firstvertex = surface->num_firstvertex;
6917 endvertex = surface->num_firstvertex + surface->num_vertices;
6918 for (;j < texturenumsurfaces;j++)
6920 surface2 = texturesurfacelist[j];
6921 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6923 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6924 batchtriangles += surface2->num_triangles;
6925 firstvertex = min(firstvertex, surface2->num_firstvertex);
6926 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6928 surface2 = texturesurfacelist[j-1];
6929 numvertices = endvertex - firstvertex;
6930 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6933 else if (r_batchmode.integer == 1)
6936 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6937 for (i = 0;i < texturenumsurfaces;i = j)
6939 surface = texturesurfacelist[i];
6940 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6941 if (texturesurfacelist[j] != surface2)
6943 Con_Printf(" %i", j - i);
6946 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6948 for (i = 0;i < texturenumsurfaces;i = j)
6950 surface = texturesurfacelist[i];
6951 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6952 if (deluxemaptexunit >= 0)
6953 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6954 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6955 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6958 Con_Printf(" %i", j - i);
6960 surface2 = texturesurfacelist[j-1];
6961 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6962 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6963 GL_LockArrays(surface->num_firstvertex, numvertices);
6964 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6972 for (i = 0;i < texturenumsurfaces;i++)
6974 surface = texturesurfacelist[i];
6975 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6976 if (deluxemaptexunit >= 0)
6977 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6978 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6979 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);
6984 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6987 int texturesurfaceindex;
6988 if (r_showsurfaces.integer == 2)
6990 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6992 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6993 for (j = 0;j < surface->num_triangles;j++)
6995 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6996 GL_Color(f, f, f, 1);
6997 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7003 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7005 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7006 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7007 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);
7008 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7009 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);
7014 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7016 int texturesurfaceindex;
7020 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7022 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7023 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
7031 rsurface.lightmapcolor4f = rsurface.array_color4f;
7032 rsurface.lightmapcolor4f_bufferobject = 0;
7033 rsurface.lightmapcolor4f_bufferoffset = 0;
7036 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7038 int texturesurfaceindex;
7044 if (rsurface.lightmapcolor4f)
7046 // generate color arrays for the surfaces in this list
7047 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7049 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7050 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)
7052 f = RSurf_FogVertex(v);
7062 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7064 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7065 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)
7067 f = RSurf_FogVertex(v);
7075 rsurface.lightmapcolor4f = rsurface.array_color4f;
7076 rsurface.lightmapcolor4f_bufferobject = 0;
7077 rsurface.lightmapcolor4f_bufferoffset = 0;
7080 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7082 int texturesurfaceindex;
7088 if (!rsurface.lightmapcolor4f)
7090 // generate color arrays for the surfaces in this list
7091 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7093 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7094 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)
7096 f = RSurf_FogVertex(v);
7097 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7098 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7099 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7103 rsurface.lightmapcolor4f = rsurface.array_color4f;
7104 rsurface.lightmapcolor4f_bufferobject = 0;
7105 rsurface.lightmapcolor4f_bufferoffset = 0;
7108 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7110 int texturesurfaceindex;
7114 if (!rsurface.lightmapcolor4f)
7116 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7118 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7119 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)
7127 rsurface.lightmapcolor4f = rsurface.array_color4f;
7128 rsurface.lightmapcolor4f_bufferobject = 0;
7129 rsurface.lightmapcolor4f_bufferoffset = 0;
7132 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7134 int texturesurfaceindex;
7138 if (!rsurface.lightmapcolor4f)
7140 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7142 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7143 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)
7145 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7146 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7147 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7151 rsurface.lightmapcolor4f = rsurface.array_color4f;
7152 rsurface.lightmapcolor4f_bufferobject = 0;
7153 rsurface.lightmapcolor4f_bufferoffset = 0;
7156 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7159 rsurface.lightmapcolor4f = NULL;
7160 rsurface.lightmapcolor4f_bufferobject = 0;
7161 rsurface.lightmapcolor4f_bufferoffset = 0;
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_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7169 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7171 // TODO: optimize applyfog && applycolor case
7172 // just apply fog if necessary, and tint the fog color array if necessary
7173 rsurface.lightmapcolor4f = NULL;
7174 rsurface.lightmapcolor4f_bufferobject = 0;
7175 rsurface.lightmapcolor4f_bufferoffset = 0;
7176 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7177 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7178 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7179 GL_Color(r, g, b, a);
7180 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7183 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7185 int texturesurfaceindex;
7189 if (texturesurfacelist[0]->lightmapinfo)
7191 // generate color arrays for the surfaces in this list
7192 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7194 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7195 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7197 if (surface->lightmapinfo->samples)
7199 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7200 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7201 VectorScale(lm, scale, c);
7202 if (surface->lightmapinfo->styles[1] != 255)
7204 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7206 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7207 VectorMA(c, scale, lm, c);
7208 if (surface->lightmapinfo->styles[2] != 255)
7211 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7212 VectorMA(c, scale, lm, c);
7213 if (surface->lightmapinfo->styles[3] != 255)
7216 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7217 VectorMA(c, scale, lm, c);
7227 rsurface.lightmapcolor4f = rsurface.array_color4f;
7228 rsurface.lightmapcolor4f_bufferobject = 0;
7229 rsurface.lightmapcolor4f_bufferoffset = 0;
7233 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7234 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7235 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7237 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7238 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7239 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7240 GL_Color(r, g, b, a);
7241 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7244 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7246 int texturesurfaceindex;
7253 vec3_t ambientcolor;
7254 vec3_t diffusecolor;
7258 VectorCopy(rsurface.modellight_lightdir, lightdir);
7259 f = 0.5f * r_refdef.lightmapintensity;
7260 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7261 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7262 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7263 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7264 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7265 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7267 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7269 // generate color arrays for the surfaces in this list
7270 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7272 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7273 int numverts = surface->num_vertices;
7274 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7275 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7276 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7277 // q3-style directional shading
7278 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7280 if ((f = DotProduct(n, lightdir)) > 0)
7281 VectorMA(ambientcolor, f, diffusecolor, c);
7283 VectorCopy(ambientcolor, c);
7291 rsurface.lightmapcolor4f = rsurface.array_color4f;
7292 rsurface.lightmapcolor4f_bufferobject = 0;
7293 rsurface.lightmapcolor4f_bufferoffset = 0;
7294 *applycolor = false;
7298 *r = ambientcolor[0];
7299 *g = ambientcolor[1];
7300 *b = ambientcolor[2];
7301 rsurface.lightmapcolor4f = NULL;
7302 rsurface.lightmapcolor4f_bufferobject = 0;
7303 rsurface.lightmapcolor4f_bufferoffset = 0;
7307 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7309 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7310 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7311 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7312 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7313 GL_Color(r, g, b, a);
7314 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7317 void RSurf_SetupDepthAndCulling(void)
7319 // submodels are biased to avoid z-fighting with world surfaces that they
7320 // may be exactly overlapping (avoids z-fighting artifacts on certain
7321 // doors and things in Quake maps)
7322 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7323 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7324 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7325 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7328 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7330 // transparent sky would be ridiculous
7331 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7333 R_SetupGenericShader(false);
7334 skyrenderlater = true;
7335 RSurf_SetupDepthAndCulling();
7337 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7338 // skymasking on them, and Quake3 never did sky masking (unlike
7339 // software Quake and software Quake2), so disable the sky masking
7340 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7341 // and skymasking also looks very bad when noclipping outside the
7342 // level, so don't use it then either.
7343 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7345 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7346 R_Mesh_ColorPointer(NULL, 0, 0);
7347 R_Mesh_ResetTextureState();
7348 if (skyrendermasked)
7350 R_SetupDepthOrShadowShader();
7351 // depth-only (masking)
7352 GL_ColorMask(0,0,0,0);
7353 // just to make sure that braindead drivers don't draw
7354 // anything despite that colormask...
7355 GL_BlendFunc(GL_ZERO, GL_ONE);
7359 R_SetupGenericShader(false);
7361 GL_BlendFunc(GL_ONE, GL_ZERO);
7363 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7364 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7365 if (skyrendermasked)
7366 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7368 R_Mesh_ResetTextureState();
7369 GL_Color(1, 1, 1, 1);
7372 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7374 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7377 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7378 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7379 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7380 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7381 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7382 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7383 if (rsurface.texture->backgroundcurrentskinframe)
7385 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7386 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7387 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7388 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7390 if(rsurface.texture->colormapping)
7392 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7393 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7395 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7396 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7397 R_Mesh_ColorPointer(NULL, 0, 0);
7399 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7401 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7403 // render background
7404 GL_BlendFunc(GL_ONE, GL_ZERO);
7406 GL_AlphaTest(false);
7408 GL_Color(1, 1, 1, 1);
7409 R_Mesh_ColorPointer(NULL, 0, 0);
7411 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7412 if (r_glsl_permutation)
7414 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7415 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7416 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7417 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7418 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7419 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7420 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);
7422 GL_LockArrays(0, 0);
7424 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7425 GL_DepthMask(false);
7426 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7427 R_Mesh_ColorPointer(NULL, 0, 0);
7429 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7430 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7431 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7434 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7435 if (!r_glsl_permutation)
7438 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7439 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7440 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7441 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7442 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7443 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7445 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7447 GL_BlendFunc(GL_ONE, GL_ZERO);
7449 GL_AlphaTest(false);
7453 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7454 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7455 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7458 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7460 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7461 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);
7463 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7467 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7468 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);
7470 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7472 GL_LockArrays(0, 0);
7475 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7477 // OpenGL 1.3 path - anything not completely ancient
7478 int texturesurfaceindex;
7479 qboolean applycolor;
7483 const texturelayer_t *layer;
7484 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7486 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7489 int layertexrgbscale;
7490 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7492 if (layerindex == 0)
7496 GL_AlphaTest(false);
7497 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7500 GL_DepthMask(layer->depthmask && writedepth);
7501 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7502 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7504 layertexrgbscale = 4;
7505 VectorScale(layer->color, 0.25f, layercolor);
7507 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7509 layertexrgbscale = 2;
7510 VectorScale(layer->color, 0.5f, layercolor);
7514 layertexrgbscale = 1;
7515 VectorScale(layer->color, 1.0f, layercolor);
7517 layercolor[3] = layer->color[3];
7518 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7519 R_Mesh_ColorPointer(NULL, 0, 0);
7520 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7521 switch (layer->type)
7523 case TEXTURELAYERTYPE_LITTEXTURE:
7524 memset(&m, 0, sizeof(m));
7525 m.tex[0] = R_GetTexture(r_texture_white);
7526 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7527 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7528 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7529 m.tex[1] = R_GetTexture(layer->texture);
7530 m.texmatrix[1] = layer->texmatrix;
7531 m.texrgbscale[1] = layertexrgbscale;
7532 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7533 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7534 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7535 R_Mesh_TextureState(&m);
7536 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7537 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7538 else if (rsurface.uselightmaptexture)
7539 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7541 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7543 case TEXTURELAYERTYPE_TEXTURE:
7544 memset(&m, 0, sizeof(m));
7545 m.tex[0] = R_GetTexture(layer->texture);
7546 m.texmatrix[0] = layer->texmatrix;
7547 m.texrgbscale[0] = layertexrgbscale;
7548 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7549 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7550 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7551 R_Mesh_TextureState(&m);
7552 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7554 case TEXTURELAYERTYPE_FOG:
7555 memset(&m, 0, sizeof(m));
7556 m.texrgbscale[0] = layertexrgbscale;
7559 m.tex[0] = R_GetTexture(layer->texture);
7560 m.texmatrix[0] = layer->texmatrix;
7561 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7562 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7563 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7565 R_Mesh_TextureState(&m);
7566 // generate a color array for the fog pass
7567 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7568 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7574 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7575 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)
7577 f = 1 - RSurf_FogVertex(v);
7578 c[0] = layercolor[0];
7579 c[1] = layercolor[1];
7580 c[2] = layercolor[2];
7581 c[3] = f * layercolor[3];
7584 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7587 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7589 GL_LockArrays(0, 0);
7592 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7594 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7595 GL_AlphaTest(false);
7599 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7601 // OpenGL 1.1 - crusty old voodoo path
7602 int texturesurfaceindex;
7606 const texturelayer_t *layer;
7607 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7609 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7611 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7613 if (layerindex == 0)
7617 GL_AlphaTest(false);
7618 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7621 GL_DepthMask(layer->depthmask && writedepth);
7622 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7623 R_Mesh_ColorPointer(NULL, 0, 0);
7624 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7625 switch (layer->type)
7627 case TEXTURELAYERTYPE_LITTEXTURE:
7628 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7630 // two-pass lit texture with 2x rgbscale
7631 // first the lightmap pass
7632 memset(&m, 0, sizeof(m));
7633 m.tex[0] = R_GetTexture(r_texture_white);
7634 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7635 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7636 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7637 R_Mesh_TextureState(&m);
7638 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7639 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7640 else if (rsurface.uselightmaptexture)
7641 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7643 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7644 GL_LockArrays(0, 0);
7645 // then apply the texture to it
7646 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7647 memset(&m, 0, sizeof(m));
7648 m.tex[0] = R_GetTexture(layer->texture);
7649 m.texmatrix[0] = layer->texmatrix;
7650 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7651 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7652 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7653 R_Mesh_TextureState(&m);
7654 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);
7658 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7659 memset(&m, 0, sizeof(m));
7660 m.tex[0] = R_GetTexture(layer->texture);
7661 m.texmatrix[0] = layer->texmatrix;
7662 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7663 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7664 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7665 R_Mesh_TextureState(&m);
7666 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7667 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);
7669 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);
7672 case TEXTURELAYERTYPE_TEXTURE:
7673 // singletexture unlit texture with transparency support
7674 memset(&m, 0, sizeof(m));
7675 m.tex[0] = R_GetTexture(layer->texture);
7676 m.texmatrix[0] = layer->texmatrix;
7677 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7678 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7679 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7680 R_Mesh_TextureState(&m);
7681 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);
7683 case TEXTURELAYERTYPE_FOG:
7684 // singletexture fogging
7685 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7688 memset(&m, 0, sizeof(m));
7689 m.tex[0] = R_GetTexture(layer->texture);
7690 m.texmatrix[0] = layer->texmatrix;
7691 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7692 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7693 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7694 R_Mesh_TextureState(&m);
7697 R_Mesh_ResetTextureState();
7698 // generate a color array for the fog pass
7699 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7705 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7706 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)
7708 f = 1 - RSurf_FogVertex(v);
7709 c[0] = layer->color[0];
7710 c[1] = layer->color[1];
7711 c[2] = layer->color[2];
7712 c[3] = f * layer->color[3];
7715 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7718 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7720 GL_LockArrays(0, 0);
7723 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7725 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7726 GL_AlphaTest(false);
7730 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7734 GL_AlphaTest(false);
7735 R_Mesh_ColorPointer(NULL, 0, 0);
7736 R_Mesh_ResetTextureState();
7737 R_SetupGenericShader(false);
7739 if(rsurface.texture && rsurface.texture->currentskinframe)
7741 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7742 c[3] *= rsurface.texture->currentalpha;
7752 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7754 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7755 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7756 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7759 // brighten it up (as texture value 127 means "unlit")
7760 c[0] *= 2 * r_refdef.view.colorscale;
7761 c[1] *= 2 * r_refdef.view.colorscale;
7762 c[2] *= 2 * r_refdef.view.colorscale;
7764 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7765 c[3] *= r_wateralpha.value;
7767 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7769 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7770 GL_DepthMask(false);
7772 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7774 GL_BlendFunc(GL_ONE, GL_ONE);
7775 GL_DepthMask(false);
7777 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7779 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7780 GL_DepthMask(false);
7782 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7784 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7785 GL_DepthMask(false);
7789 GL_BlendFunc(GL_ONE, GL_ZERO);
7790 GL_DepthMask(writedepth);
7793 rsurface.lightmapcolor4f = NULL;
7795 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7797 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7799 rsurface.lightmapcolor4f = NULL;
7800 rsurface.lightmapcolor4f_bufferobject = 0;
7801 rsurface.lightmapcolor4f_bufferoffset = 0;
7803 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7805 qboolean applycolor = true;
7808 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7810 r_refdef.lightmapintensity = 1;
7811 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7812 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7816 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7818 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7819 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7820 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7823 if(!rsurface.lightmapcolor4f)
7824 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7826 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7827 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7828 if(r_refdef.fogenabled)
7829 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7831 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7832 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7835 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7838 RSurf_SetupDepthAndCulling();
7839 if (r_showsurfaces.integer == 3)
7840 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7841 else if (r_glsl.integer && gl_support_fragment_shader)
7842 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7843 else if (gl_combine.integer && r_textureunits.integer >= 2)
7844 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7846 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7850 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7853 RSurf_SetupDepthAndCulling();
7854 if (r_showsurfaces.integer == 3)
7855 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7856 else if (r_glsl.integer && gl_support_fragment_shader)
7857 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7858 else if (gl_combine.integer && r_textureunits.integer >= 2)
7859 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7861 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7865 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7868 int texturenumsurfaces, endsurface;
7870 const msurface_t *surface;
7871 const msurface_t *texturesurfacelist[1024];
7873 // if the model is static it doesn't matter what value we give for
7874 // wantnormals and wanttangents, so this logic uses only rules applicable
7875 // to a model, knowing that they are meaningless otherwise
7876 if (ent == r_refdef.scene.worldentity)
7877 RSurf_ActiveWorldEntity();
7878 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7879 RSurf_ActiveModelEntity(ent, false, false);
7881 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7883 for (i = 0;i < numsurfaces;i = j)
7886 surface = rsurface.modelsurfaces + surfacelist[i];
7887 texture = surface->texture;
7888 rsurface.texture = R_GetCurrentTexture(texture);
7889 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7890 // scan ahead until we find a different texture
7891 endsurface = min(i + 1024, numsurfaces);
7892 texturenumsurfaces = 0;
7893 texturesurfacelist[texturenumsurfaces++] = surface;
7894 for (;j < endsurface;j++)
7896 surface = rsurface.modelsurfaces + surfacelist[j];
7897 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7899 texturesurfacelist[texturenumsurfaces++] = surface;
7901 // render the range of surfaces
7902 if (ent == r_refdef.scene.worldentity)
7903 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7905 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7907 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7908 GL_AlphaTest(false);
7911 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7913 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7917 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7919 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7921 RSurf_SetupDepthAndCulling();
7922 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7923 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7925 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7927 RSurf_SetupDepthAndCulling();
7928 GL_AlphaTest(false);
7929 R_Mesh_ColorPointer(NULL, 0, 0);
7930 R_Mesh_ResetTextureState();
7931 R_SetupGenericShader(false);
7932 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7934 GL_BlendFunc(GL_ONE, GL_ZERO);
7935 GL_Color(0, 0, 0, 1);
7936 GL_DepthTest(writedepth);
7937 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7939 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7941 RSurf_SetupDepthAndCulling();
7942 GL_AlphaTest(false);
7943 R_Mesh_ColorPointer(NULL, 0, 0);
7944 R_Mesh_ResetTextureState();
7945 R_SetupGenericShader(false);
7946 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7948 GL_BlendFunc(GL_ONE, GL_ZERO);
7950 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7952 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7953 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7954 else if (!rsurface.texture->currentnumlayers)
7956 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7958 // transparent surfaces get pushed off into the transparent queue
7959 int surfacelistindex;
7960 const msurface_t *surface;
7961 vec3_t tempcenter, center;
7962 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7964 surface = texturesurfacelist[surfacelistindex];
7965 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7966 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7967 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7968 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7969 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7974 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7975 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7980 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7984 // break the surface list down into batches by texture and use of lightmapping
7985 for (i = 0;i < numsurfaces;i = j)
7988 // texture is the base texture pointer, rsurface.texture is the
7989 // current frame/skin the texture is directing us to use (for example
7990 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7991 // use skin 1 instead)
7992 texture = surfacelist[i]->texture;
7993 rsurface.texture = R_GetCurrentTexture(texture);
7994 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7995 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7997 // if this texture is not the kind we want, skip ahead to the next one
7998 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8002 // simply scan ahead until we find a different texture or lightmap state
8003 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8005 // render the range of surfaces
8006 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
8010 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
8015 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8017 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8019 RSurf_SetupDepthAndCulling();
8020 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8021 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8023 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8025 RSurf_SetupDepthAndCulling();
8026 GL_AlphaTest(false);
8027 R_Mesh_ColorPointer(NULL, 0, 0);
8028 R_Mesh_ResetTextureState();
8029 R_SetupGenericShader(false);
8030 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8032 GL_BlendFunc(GL_ONE, GL_ZERO);
8033 GL_Color(0, 0, 0, 1);
8034 GL_DepthTest(writedepth);
8035 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8037 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8039 RSurf_SetupDepthAndCulling();
8040 GL_AlphaTest(false);
8041 R_Mesh_ColorPointer(NULL, 0, 0);
8042 R_Mesh_ResetTextureState();
8043 R_SetupGenericShader(false);
8044 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8046 GL_BlendFunc(GL_ONE, GL_ZERO);
8048 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8050 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8051 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8052 else if (!rsurface.texture->currentnumlayers)
8054 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8056 // transparent surfaces get pushed off into the transparent queue
8057 int surfacelistindex;
8058 const msurface_t *surface;
8059 vec3_t tempcenter, center;
8060 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8062 surface = texturesurfacelist[surfacelistindex];
8063 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8064 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8065 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8066 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8067 if (queueentity->transparent_offset) // transparent offset
8069 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8070 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8071 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8073 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8078 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8079 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8084 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8088 // break the surface list down into batches by texture and use of lightmapping
8089 for (i = 0;i < numsurfaces;i = j)
8092 // texture is the base texture pointer, rsurface.texture is the
8093 // current frame/skin the texture is directing us to use (for example
8094 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8095 // use skin 1 instead)
8096 texture = surfacelist[i]->texture;
8097 rsurface.texture = R_GetCurrentTexture(texture);
8098 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8099 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8101 // if this texture is not the kind we want, skip ahead to the next one
8102 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8106 // simply scan ahead until we find a different texture or lightmap state
8107 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8109 // render the range of surfaces
8110 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8114 float locboxvertex3f[6*4*3] =
8116 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8117 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8118 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8119 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8120 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8121 1,0,0, 0,0,0, 0,1,0, 1,1,0
8124 unsigned short locboxelements[6*2*3] =
8134 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8137 cl_locnode_t *loc = (cl_locnode_t *)ent;
8139 float vertex3f[6*4*3];
8141 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8142 GL_DepthMask(false);
8143 GL_DepthRange(0, 1);
8144 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8146 GL_CullFace(GL_NONE);
8147 R_Mesh_Matrix(&identitymatrix);
8149 R_Mesh_VertexPointer(vertex3f, 0, 0);
8150 R_Mesh_ColorPointer(NULL, 0, 0);
8151 R_Mesh_ResetTextureState();
8152 R_SetupGenericShader(false);
8155 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8156 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8157 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8158 surfacelist[0] < 0 ? 0.5f : 0.125f);
8160 if (VectorCompare(loc->mins, loc->maxs))
8162 VectorSet(size, 2, 2, 2);
8163 VectorMA(loc->mins, -0.5f, size, mins);
8167 VectorCopy(loc->mins, mins);
8168 VectorSubtract(loc->maxs, loc->mins, size);
8171 for (i = 0;i < 6*4*3;)
8172 for (j = 0;j < 3;j++, i++)
8173 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8175 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8178 void R_DrawLocs(void)
8181 cl_locnode_t *loc, *nearestloc;
8183 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8184 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8186 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8187 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8191 void R_DrawDebugModel(entity_render_t *ent)
8193 int i, j, k, l, flagsmask;
8194 const int *elements;
8196 const msurface_t *surface;
8197 dp_model_t *model = ent->model;
8200 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8202 R_Mesh_ColorPointer(NULL, 0, 0);
8203 R_Mesh_ResetTextureState();
8204 R_SetupGenericShader(false);
8205 GL_DepthRange(0, 1);
8206 GL_DepthTest(!r_showdisabledepthtest.integer);
8207 GL_DepthMask(false);
8208 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8210 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8212 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8213 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8215 if (brush->colbrushf && brush->colbrushf->numtriangles)
8217 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8218 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);
8219 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8222 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8224 if (surface->num_collisiontriangles)
8226 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8227 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);
8228 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8233 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8235 if (r_showtris.integer || r_shownormals.integer)
8237 if (r_showdisabledepthtest.integer)
8239 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8240 GL_DepthMask(false);
8244 GL_BlendFunc(GL_ONE, GL_ZERO);
8247 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8249 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8251 rsurface.texture = R_GetCurrentTexture(surface->texture);
8252 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8254 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8255 if (r_showtris.value > 0)
8257 if (!rsurface.texture->currentlayers->depthmask)
8258 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8259 else if (ent == r_refdef.scene.worldentity)
8260 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8262 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8263 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8264 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8265 R_Mesh_ColorPointer(NULL, 0, 0);
8266 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8267 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8268 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8269 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);
8270 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8273 if (r_shownormals.value < 0)
8276 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8278 VectorCopy(rsurface.vertex3f + l * 3, v);
8279 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8280 qglVertex3f(v[0], v[1], v[2]);
8281 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8282 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8283 qglVertex3f(v[0], v[1], v[2]);
8288 if (r_shownormals.value > 0)
8291 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8293 VectorCopy(rsurface.vertex3f + l * 3, v);
8294 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8295 qglVertex3f(v[0], v[1], v[2]);
8296 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8297 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8298 qglVertex3f(v[0], v[1], v[2]);
8303 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8305 VectorCopy(rsurface.vertex3f + l * 3, v);
8306 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8307 qglVertex3f(v[0], v[1], v[2]);
8308 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8309 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8310 qglVertex3f(v[0], v[1], v[2]);
8315 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8317 VectorCopy(rsurface.vertex3f + l * 3, v);
8318 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8319 qglVertex3f(v[0], v[1], v[2]);
8320 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8321 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8322 qglVertex3f(v[0], v[1], v[2]);
8329 rsurface.texture = NULL;
8333 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8334 int r_maxsurfacelist = 0;
8335 const msurface_t **r_surfacelist = NULL;
8336 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8338 int i, j, endj, f, flagsmask;
8340 dp_model_t *model = r_refdef.scene.worldmodel;
8341 msurface_t *surfaces;
8342 unsigned char *update;
8343 int numsurfacelist = 0;
8347 if (r_maxsurfacelist < model->num_surfaces)
8349 r_maxsurfacelist = model->num_surfaces;
8351 Mem_Free(r_surfacelist);
8352 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8355 RSurf_ActiveWorldEntity();
8357 surfaces = model->data_surfaces;
8358 update = model->brushq1.lightmapupdateflags;
8360 // update light styles on this submodel
8361 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8363 model_brush_lightstyleinfo_t *style;
8364 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8366 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8368 int *list = style->surfacelist;
8369 style->value = r_refdef.scene.lightstylevalue[style->style];
8370 for (j = 0;j < style->numsurfaces;j++)
8371 update[list[j]] = true;
8376 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8380 R_DrawDebugModel(r_refdef.scene.worldentity);
8381 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8387 rsurface.uselightmaptexture = false;
8388 rsurface.texture = NULL;
8389 rsurface.rtlight = NULL;
8391 // add visible surfaces to draw list
8392 for (i = 0;i < model->nummodelsurfaces;i++)
8394 j = model->sortedmodelsurfaces[i];
8395 if (r_refdef.viewcache.world_surfacevisible[j])
8396 r_surfacelist[numsurfacelist++] = surfaces + j;
8398 // update lightmaps if needed
8400 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8401 if (r_refdef.viewcache.world_surfacevisible[j])
8403 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8404 // don't do anything if there were no surfaces
8405 if (!numsurfacelist)
8407 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8410 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8411 GL_AlphaTest(false);
8413 // add to stats if desired
8414 if (r_speeds.integer && !skysurfaces && !depthonly)
8416 r_refdef.stats.world_surfaces += numsurfacelist;
8417 for (j = 0;j < numsurfacelist;j++)
8418 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8420 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8423 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8425 int i, j, endj, f, flagsmask;
8427 dp_model_t *model = ent->model;
8428 msurface_t *surfaces;
8429 unsigned char *update;
8430 int numsurfacelist = 0;
8434 if (r_maxsurfacelist < model->num_surfaces)
8436 r_maxsurfacelist = model->num_surfaces;
8438 Mem_Free(r_surfacelist);
8439 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8442 // if the model is static it doesn't matter what value we give for
8443 // wantnormals and wanttangents, so this logic uses only rules applicable
8444 // to a model, knowing that they are meaningless otherwise
8445 if (ent == r_refdef.scene.worldentity)
8446 RSurf_ActiveWorldEntity();
8447 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8448 RSurf_ActiveModelEntity(ent, false, false);
8450 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8452 surfaces = model->data_surfaces;
8453 update = model->brushq1.lightmapupdateflags;
8455 // update light styles
8456 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8458 model_brush_lightstyleinfo_t *style;
8459 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8461 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8463 int *list = style->surfacelist;
8464 style->value = r_refdef.scene.lightstylevalue[style->style];
8465 for (j = 0;j < style->numsurfaces;j++)
8466 update[list[j]] = true;
8471 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8475 R_DrawDebugModel(ent);
8476 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8482 rsurface.uselightmaptexture = false;
8483 rsurface.texture = NULL;
8484 rsurface.rtlight = NULL;
8486 // add visible surfaces to draw list
8487 for (i = 0;i < model->nummodelsurfaces;i++)
8488 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8489 // don't do anything if there were no surfaces
8490 if (!numsurfacelist)
8492 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8495 // update lightmaps if needed
8497 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8499 R_BuildLightMap(ent, surfaces + j);
8500 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8501 GL_AlphaTest(false);
8503 // add to stats if desired
8504 if (r_speeds.integer && !skysurfaces && !depthonly)
8506 r_refdef.stats.entities_surfaces += numsurfacelist;
8507 for (j = 0;j < numsurfacelist;j++)
8508 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8510 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8513 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
8515 static texture_t texture;
8516 static msurface_t surface;
8517 const msurface_t *surfacelist = &surface;
8519 // fake enough texture and surface state to render this geometry
8521 texture.update_lastrenderframe = -1; // regenerate this texture
8522 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
8523 texture.currentskinframe = skinframe;
8524 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
8525 texture.specularscalemod = 1;
8526 texture.specularpowermod = 1;
8528 surface.texture = &texture;
8529 surface.num_triangles = numtriangles;
8530 surface.num_firsttriangle = firsttriangle;
8531 surface.num_vertices = numvertices;
8532 surface.num_firstvertex = firstvertex;
8535 rsurface.texture = R_GetCurrentTexture(surface.texture);
8536 rsurface.uselightmaptexture = false;
8537 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);