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_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "equalize entity lighting (exponent)"};
50 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "equalize entity lighting (level)"};
52 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
54 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"};
55 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
56 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
57 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
58 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)"};
59 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
60 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
61 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"};
62 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"};
63 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
64 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"};
65 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"};
66 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"};
67 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
68 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
69 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
70 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
71 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
72 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
73 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
74 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
75 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
76 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
77 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
78 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
79 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."};
80 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
81 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
82 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
83 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."};
84 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
85 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
86 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"};
87 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"};
88 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
89 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
91 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
92 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
93 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
94 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
95 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
96 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
97 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
98 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
100 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)"};
102 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
103 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)"};
104 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
105 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
106 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
107 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
108 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)"};
109 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)"};
110 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)"};
111 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)"};
112 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)"};
114 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)"};
115 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
116 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"};
117 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
118 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
120 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
121 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
122 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
123 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
125 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
126 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
127 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
128 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
129 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
130 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
131 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
133 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
134 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
135 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
136 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)"};
138 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"};
140 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"};
142 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
144 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
145 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
146 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"};
147 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
148 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
149 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
150 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
152 extern cvar_t v_glslgamma;
154 extern qboolean v_flipped_state;
156 static struct r_bloomstate_s
161 int bloomwidth, bloomheight;
163 int screentexturewidth, screentextureheight;
164 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
166 int bloomtexturewidth, bloomtextureheight;
167 rtexture_t *texture_bloom;
169 // arrays for rendering the screen passes
170 float screentexcoord2f[8];
171 float bloomtexcoord2f[8];
172 float offsettexcoord2f[8];
174 r_viewport_t viewport;
178 r_waterstate_t r_waterstate;
180 /// shadow volume bsp struct with automatically growing nodes buffer
183 rtexture_t *r_texture_blanknormalmap;
184 rtexture_t *r_texture_white;
185 rtexture_t *r_texture_grey128;
186 rtexture_t *r_texture_black;
187 rtexture_t *r_texture_notexture;
188 rtexture_t *r_texture_whitecube;
189 rtexture_t *r_texture_normalizationcube;
190 rtexture_t *r_texture_fogattenuation;
191 rtexture_t *r_texture_gammaramps;
192 unsigned int r_texture_gammaramps_serial;
193 //rtexture_t *r_texture_fogintensity;
195 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
196 unsigned int r_numqueries;
197 unsigned int r_maxqueries;
199 typedef struct r_qwskincache_s
201 char name[MAX_QPATH];
202 skinframe_t *skinframe;
206 static r_qwskincache_t *r_qwskincache;
207 static int r_qwskincache_size;
209 /// vertex coordinates for a quad that covers the screen exactly
210 const float r_screenvertex3f[12] =
218 extern void R_DrawModelShadows(void);
220 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
223 for (i = 0;i < verts;i++)
234 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
237 for (i = 0;i < verts;i++)
247 // FIXME: move this to client?
250 if (gamemode == GAME_NEHAHRA)
252 Cvar_Set("gl_fogenable", "0");
253 Cvar_Set("gl_fogdensity", "0.2");
254 Cvar_Set("gl_fogred", "0.3");
255 Cvar_Set("gl_foggreen", "0.3");
256 Cvar_Set("gl_fogblue", "0.3");
258 r_refdef.fog_density = 0;
259 r_refdef.fog_red = 0;
260 r_refdef.fog_green = 0;
261 r_refdef.fog_blue = 0;
262 r_refdef.fog_alpha = 1;
263 r_refdef.fog_start = 0;
264 r_refdef.fog_end = 0;
267 static void R_BuildBlankTextures(void)
269 unsigned char data[4];
270 data[2] = 128; // normal X
271 data[1] = 128; // normal Y
272 data[0] = 255; // normal Z
273 data[3] = 128; // height
274 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
279 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
284 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
289 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 static void R_BuildNoTexture(void)
295 unsigned char pix[16][16][4];
296 // this makes a light grey/dark grey checkerboard texture
297 for (y = 0;y < 16;y++)
299 for (x = 0;x < 16;x++)
301 if ((y < 8) ^ (x < 8))
317 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
320 static void R_BuildWhiteCube(void)
322 unsigned char data[6*1*1*4];
323 memset(data, 255, sizeof(data));
324 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
327 static void R_BuildNormalizationCube(void)
331 vec_t s, t, intensity;
333 unsigned char data[6][NORMSIZE][NORMSIZE][4];
334 for (side = 0;side < 6;side++)
336 for (y = 0;y < NORMSIZE;y++)
338 for (x = 0;x < NORMSIZE;x++)
340 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
341 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
376 intensity = 127.0f / sqrt(DotProduct(v, v));
377 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
378 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
379 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
380 data[side][y][x][3] = 255;
384 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
387 static void R_BuildFogTexture(void)
391 unsigned char data1[FOGWIDTH][4];
392 //unsigned char data2[FOGWIDTH][4];
395 r_refdef.fogmasktable_start = r_refdef.fog_start;
396 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
397 r_refdef.fogmasktable_range = r_refdef.fogrange;
398 r_refdef.fogmasktable_density = r_refdef.fog_density;
400 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
401 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
403 d = (x * r - r_refdef.fogmasktable_start);
404 if(developer.integer >= 100)
405 Con_Printf("%f ", d);
407 if (r_fog_exp2.integer)
408 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
410 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
411 if(developer.integer >= 100)
412 Con_Printf(" : %f ", alpha);
413 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
414 if(developer.integer >= 100)
415 Con_Printf(" = %f\n", alpha);
416 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
419 for (x = 0;x < FOGWIDTH;x++)
421 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
426 //data2[x][0] = 255 - b;
427 //data2[x][1] = 255 - b;
428 //data2[x][2] = 255 - b;
431 if (r_texture_fogattenuation)
433 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
434 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
438 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);
439 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
443 static const char *builtinshaderstring =
444 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
445 "// written by Forest 'LordHavoc' Hale\n"
447 "// enable various extensions depending on permutation:\n"
449 "#ifdef USESHADOWMAPRECT\n"
450 "# extension GL_ARB_texture_rectangle : enable\n"
453 "#ifdef USESHADOWMAP2D\n"
454 "# ifdef GL_EXT_gpu_shader4\n"
455 "# extension GL_EXT_gpu_shader4 : enable\n"
457 "# ifdef GL_ARB_texture_gather\n"
458 "# extension GL_ARB_texture_gather : enable\n"
460 "# ifdef GL_AMD_texture_texture4\n"
461 "# extension GL_AMD_texture_texture4 : enable\n"
466 "#ifdef USESHADOWMAPCUBE\n"
467 "# extension GL_EXT_gpu_shader4 : enable\n"
470 "#ifdef USESHADOWSAMPLER\n"
471 "# extension GL_ARB_shadow : enable\n"
474 "// common definitions between vertex shader and fragment shader:\n"
476 "//#ifdef __GLSL_CG_DATA_TYPES\n"
477 "//# define myhalf half\n"
478 "//# define myhalf2 half2\n"
479 "//# define myhalf3half3\n"
480 "//# define myhalf4 half4\n"
482 "# define myhalf float\n"
483 "# define myhalf2 vec2\n"
484 "# define myhalf3 vec3\n"
485 "# define myhalf4 vec4\n"
488 "#ifdef MODE_DEPTH_OR_SHADOW\n"
490 "# ifdef VERTEX_SHADER\n"
493 " gl_Position = ftransform();\n"
498 "#ifdef MODE_SHOWDEPTH\n"
499 "# ifdef VERTEX_SHADER\n"
502 " gl_Position = ftransform();\n"
503 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
506 "# ifdef FRAGMENT_SHADER\n"
509 " gl_FragColor = gl_Color;\n"
513 "#else // !MODE_SHOWDEPTH\n"
515 "#ifdef MODE_POSTPROCESS\n"
516 "# ifdef VERTEX_SHADER\n"
519 " gl_FrontColor = gl_Color;\n"
520 " gl_Position = ftransform();\n"
521 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
523 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
527 "# ifdef FRAGMENT_SHADER\n"
529 "uniform sampler2D Texture_First;\n"
531 "uniform sampler2D Texture_Second;\n"
533 "#ifdef USEGAMMARAMPS\n"
534 "uniform sampler2D Texture_GammaRamps;\n"
536 "#ifdef USESATURATION\n"
537 "uniform float Saturation;\n"
539 "#ifdef USEVIEWTINT\n"
540 "uniform vec4 TintColor;\n"
542 "//uncomment these if you want to use them:\n"
543 "uniform vec4 UserVec1;\n"
544 "// uniform vec4 UserVec2;\n"
545 "// uniform vec4 UserVec3;\n"
546 "// uniform vec4 UserVec4;\n"
547 "// uniform float ClientTime;\n"
548 "uniform vec2 PixelSize;\n"
551 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
553 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
555 "#ifdef USEVIEWTINT\n"
556 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
559 "#ifdef USEPOSTPROCESSING\n"
560 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
561 "// 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"
562 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
563 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
564 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
565 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
566 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
567 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
570 "#ifdef USESATURATION\n"
571 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
572 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
573 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
574 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
577 "#ifdef USEGAMMARAMPS\n"
578 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
579 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
580 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
587 "#ifdef MODE_GENERIC\n"
588 "# ifdef VERTEX_SHADER\n"
591 " gl_FrontColor = gl_Color;\n"
592 "# ifdef USEDIFFUSE\n"
593 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
595 "# ifdef USESPECULAR\n"
596 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
598 " gl_Position = ftransform();\n"
601 "# ifdef FRAGMENT_SHADER\n"
603 "# ifdef USEDIFFUSE\n"
604 "uniform sampler2D Texture_First;\n"
606 "# ifdef USESPECULAR\n"
607 "uniform sampler2D Texture_Second;\n"
612 " gl_FragColor = gl_Color;\n"
613 "# ifdef USEDIFFUSE\n"
614 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
617 "# ifdef USESPECULAR\n"
618 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
620 "# ifdef USECOLORMAPPING\n"
621 " gl_FragColor *= tex2;\n"
624 " gl_FragColor += tex2;\n"
626 "# ifdef USEVERTEXTEXTUREBLEND\n"
627 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
632 "#else // !MODE_GENERIC\n"
634 "varying vec2 TexCoord;\n"
635 "#ifdef USEVERTEXTEXTUREBLEND\n"
636 "varying vec2 TexCoord2;\n"
638 "varying vec2 TexCoordLightmap;\n"
640 "#ifdef MODE_LIGHTSOURCE\n"
641 "varying vec3 CubeVector;\n"
644 "#ifdef MODE_LIGHTSOURCE\n"
645 "varying vec3 LightVector;\n"
647 "#ifdef MODE_LIGHTDIRECTION\n"
648 "varying vec3 LightVector;\n"
651 "varying vec3 EyeVector;\n"
653 "varying vec3 EyeVectorModelSpace;\n"
656 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
657 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
658 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
660 "#ifdef MODE_WATER\n"
661 "varying vec4 ModelViewProjectionPosition;\n"
663 "#ifdef MODE_REFRACTION\n"
664 "varying vec4 ModelViewProjectionPosition;\n"
666 "#ifdef USEREFLECTION\n"
667 "varying vec4 ModelViewProjectionPosition;\n"
674 "// vertex shader specific:\n"
675 "#ifdef VERTEX_SHADER\n"
677 "uniform vec3 LightPosition;\n"
678 "uniform vec3 EyePosition;\n"
679 "uniform vec3 LightDir;\n"
681 "// 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"
685 " gl_FrontColor = gl_Color;\n"
686 " // copy the surface texcoord\n"
687 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
688 "#ifdef USEVERTEXTEXTUREBLEND\n"
689 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
691 "#ifndef MODE_LIGHTSOURCE\n"
692 "# ifndef MODE_LIGHTDIRECTION\n"
693 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
697 "#ifdef MODE_LIGHTSOURCE\n"
698 " // transform vertex position into light attenuation/cubemap space\n"
699 " // (-1 to +1 across the light box)\n"
700 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
702 " // transform unnormalized light direction into tangent space\n"
703 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
704 " // normalize it per pixel)\n"
705 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
706 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
707 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
708 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
711 "#ifdef MODE_LIGHTDIRECTION\n"
712 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
713 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
714 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
717 " // transform unnormalized eye direction into tangent space\n"
719 " vec3 EyeVectorModelSpace;\n"
721 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
722 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
723 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
724 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
726 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
727 " VectorS = gl_MultiTexCoord1.xyz;\n"
728 " VectorT = gl_MultiTexCoord2.xyz;\n"
729 " VectorR = gl_MultiTexCoord3.xyz;\n"
732 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
733 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
734 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
735 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
738 "// transform vertex to camera space, using ftransform to match non-VS\n"
740 " gl_Position = ftransform();\n"
742 "#ifdef MODE_WATER\n"
743 " ModelViewProjectionPosition = gl_Position;\n"
745 "#ifdef MODE_REFRACTION\n"
746 " ModelViewProjectionPosition = gl_Position;\n"
748 "#ifdef USEREFLECTION\n"
749 " ModelViewProjectionPosition = gl_Position;\n"
753 "#endif // VERTEX_SHADER\n"
758 "// fragment shader specific:\n"
759 "#ifdef FRAGMENT_SHADER\n"
761 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
762 "uniform sampler2D Texture_Normal;\n"
763 "uniform sampler2D Texture_Color;\n"
764 "uniform sampler2D Texture_Gloss;\n"
765 "uniform sampler2D Texture_Glow;\n"
766 "uniform sampler2D Texture_SecondaryNormal;\n"
767 "uniform sampler2D Texture_SecondaryColor;\n"
768 "uniform sampler2D Texture_SecondaryGloss;\n"
769 "uniform sampler2D Texture_SecondaryGlow;\n"
770 "uniform sampler2D Texture_Pants;\n"
771 "uniform sampler2D Texture_Shirt;\n"
772 "uniform sampler2D Texture_FogMask;\n"
773 "uniform sampler2D Texture_Lightmap;\n"
774 "uniform sampler2D Texture_Deluxemap;\n"
775 "uniform sampler2D Texture_Refraction;\n"
776 "uniform sampler2D Texture_Reflection;\n"
777 "uniform sampler2D Texture_Attenuation;\n"
778 "uniform samplerCube Texture_Cube;\n"
780 "#define showshadowmap 0\n"
782 "#ifdef USESHADOWMAPRECT\n"
783 "# ifdef USESHADOWSAMPLER\n"
784 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
786 "uniform sampler2DRect Texture_ShadowMapRect;\n"
790 "#ifdef USESHADOWMAP2D\n"
791 "# ifdef USESHADOWSAMPLER\n"
792 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
794 "uniform sampler2D Texture_ShadowMap2D;\n"
798 "#ifdef USESHADOWMAPVSDCT\n"
799 "uniform samplerCube Texture_CubeProjection;\n"
802 "#ifdef USESHADOWMAPCUBE\n"
803 "# ifdef USESHADOWSAMPLER\n"
804 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
806 "uniform samplerCube Texture_ShadowMapCube;\n"
810 "uniform myhalf3 LightColor;\n"
811 "uniform myhalf3 AmbientColor;\n"
812 "uniform myhalf3 DiffuseColor;\n"
813 "uniform myhalf3 SpecularColor;\n"
814 "uniform myhalf3 Color_Pants;\n"
815 "uniform myhalf3 Color_Shirt;\n"
816 "uniform myhalf3 FogColor;\n"
818 "uniform myhalf4 TintColor;\n"
821 "//#ifdef MODE_WATER\n"
822 "uniform vec4 DistortScaleRefractReflect;\n"
823 "uniform vec4 ScreenScaleRefractReflect;\n"
824 "uniform vec4 ScreenCenterRefractReflect;\n"
825 "uniform myhalf4 RefractColor;\n"
826 "uniform myhalf4 ReflectColor;\n"
827 "uniform myhalf ReflectFactor;\n"
828 "uniform myhalf ReflectOffset;\n"
830 "//# ifdef MODE_REFRACTION\n"
831 "//uniform vec4 DistortScaleRefractReflect;\n"
832 "//uniform vec4 ScreenScaleRefractReflect;\n"
833 "//uniform vec4 ScreenCenterRefractReflect;\n"
834 "//uniform myhalf4 RefractColor;\n"
835 "//# ifdef USEREFLECTION\n"
836 "//uniform myhalf4 ReflectColor;\n"
839 "//# ifdef USEREFLECTION\n"
840 "//uniform vec4 DistortScaleRefractReflect;\n"
841 "//uniform vec4 ScreenScaleRefractReflect;\n"
842 "//uniform vec4 ScreenCenterRefractReflect;\n"
843 "//uniform myhalf4 ReflectColor;\n"
848 "uniform myhalf3 GlowColor;\n"
849 "uniform myhalf SceneBrightness;\n"
851 "uniform float OffsetMapping_Scale;\n"
852 "uniform float OffsetMapping_Bias;\n"
853 "uniform float FogRangeRecip;\n"
855 "uniform myhalf AmbientScale;\n"
856 "uniform myhalf DiffuseScale;\n"
857 "uniform myhalf SpecularScale;\n"
858 "uniform myhalf SpecularPower;\n"
860 "#ifdef USEOFFSETMAPPING\n"
861 "vec2 OffsetMapping(vec2 TexCoord)\n"
863 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
864 " // 14 sample relief mapping: linear search and then binary search\n"
865 " // this basically steps forward a small amount repeatedly until it finds\n"
866 " // itself inside solid, then jitters forward and back using decreasing\n"
867 " // amounts to find the impact\n"
868 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
869 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
870 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
871 " vec3 RT = vec3(TexCoord, 1);\n"
872 " OffsetVector *= 0.1;\n"
873 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
874 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
875 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
876 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
877 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
878 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
879 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
880 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
881 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
882 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
883 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
884 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
885 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
886 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
889 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
890 " // this basically moves forward the full distance, and then backs up based\n"
891 " // on height of samples\n"
892 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
893 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
894 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
895 " TexCoord += OffsetVector;\n"
896 " OffsetVector *= 0.333;\n"
897 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
898 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
899 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
900 " return TexCoord;\n"
903 "#endif // USEOFFSETMAPPING\n"
905 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
906 "uniform vec2 ShadowMap_TextureScale;\n"
907 "uniform vec4 ShadowMap_Parameters;\n"
910 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
911 "vec3 GetShadowMapTC2D(vec3 dir)\n"
913 " vec3 adir = abs(dir);\n"
914 "# ifndef USESHADOWMAPVSDCT\n"
918 " if (adir.x > adir.y)\n"
920 " if (adir.x > adir.z) // X\n"
924 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
930 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
935 " if (adir.y > adir.z) // Y\n"
939 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
945 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
949 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
950 " stc.xy += offset * ShadowMap_Parameters.y;\n"
951 " stc.z += ShadowMap_Parameters.z;\n"
952 "# if showshadowmap\n"
953 " stc.xy *= ShadowMap_TextureScale;\n"
957 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
958 " float ma = max(max(adir.x, adir.y), adir.z);\n"
959 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
960 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
961 " stc.z += ShadowMap_Parameters.z;\n"
962 "# if showshadowmap\n"
963 " stc.xy *= ShadowMap_TextureScale;\n"
968 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
970 "#ifdef USESHADOWMAPCUBE\n"
971 "vec4 GetShadowMapTCCube(vec3 dir)\n"
973 " vec3 adir = abs(dir);\n"
974 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
978 "#if !showshadowmap\n"
979 "# ifdef USESHADOWMAPRECT\n"
980 "float ShadowMapCompare(vec3 dir)\n"
982 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
984 "# ifdef USESHADOWSAMPLER\n"
986 "# ifdef USESHADOWMAPPCF\n"
987 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
988 " 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"
990 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
995 "# ifdef USESHADOWMAPPCF\n"
996 "# if USESHADOWMAPPCF > 1\n"
997 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
998 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
999 " 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"
1000 " 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"
1001 " 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"
1002 " 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"
1003 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1004 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1006 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1007 " vec2 offset = fract(shadowmaptc.xy);\n"
1008 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1009 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1010 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1011 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1012 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1015 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1023 "# ifdef USESHADOWMAP2D\n"
1024 "float ShadowMapCompare(vec3 dir)\n"
1026 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1029 "# ifdef USESHADOWSAMPLER\n"
1030 "# ifdef USESHADOWMAPPCF\n"
1031 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1032 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1033 " 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"
1035 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1038 "# ifdef USESHADOWMAPPCF\n"
1039 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1040 "# ifdef GL_ARB_texture_gather\n"
1041 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1043 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1045 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1046 " center *= ShadowMap_TextureScale;\n"
1047 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1048 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1049 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1050 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1051 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1052 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1053 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1055 "# ifdef GL_EXT_gpu_shader4\n"
1056 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1058 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1060 "# if USESHADOWMAPPCF > 1\n"
1061 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1062 " center *= ShadowMap_TextureScale;\n"
1063 " 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"
1064 " 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"
1065 " 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"
1066 " 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"
1067 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1068 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1070 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1071 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1072 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1073 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1074 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1075 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1079 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1086 "# ifdef USESHADOWMAPCUBE\n"
1087 "float ShadowMapCompare(vec3 dir)\n"
1089 " // apply depth texture cubemap as light filter\n"
1090 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1092 "# ifdef USESHADOWSAMPLER\n"
1093 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1095 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1102 "#ifdef MODE_WATER\n"
1107 "#ifdef USEOFFSETMAPPING\n"
1108 " // apply offsetmapping\n"
1109 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1110 "#define TexCoord TexCoordOffset\n"
1113 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1114 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1115 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1116 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1117 " // FIXME temporary hack to detect the case that the reflection\n"
1118 " // gets blackened at edges due to leaving the area that contains actual\n"
1120 " // Remove this 'ack once we have a better way to stop this thing from\n"
1122 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1123 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1124 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1125 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1126 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1127 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1128 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1129 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1130 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1131 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1132 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1133 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1136 "#else // !MODE_WATER\n"
1137 "#ifdef MODE_REFRACTION\n"
1139 "// refraction pass\n"
1142 "#ifdef USEOFFSETMAPPING\n"
1143 " // apply offsetmapping\n"
1144 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1145 "#define TexCoord TexCoordOffset\n"
1148 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1149 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1150 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1151 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1152 " // FIXME temporary hack to detect the case that the reflection\n"
1153 " // gets blackened at edges due to leaving the area that contains actual\n"
1155 " // Remove this 'ack once we have a better way to stop this thing from\n"
1157 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1158 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1159 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1160 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1161 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1162 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1165 "#else // !MODE_REFRACTION\n"
1168 "#ifdef USEOFFSETMAPPING\n"
1169 " // apply offsetmapping\n"
1170 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1171 "#define TexCoord TexCoordOffset\n"
1174 " // combine the diffuse textures (base, pants, shirt)\n"
1175 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1176 "#ifdef USECOLORMAPPING\n"
1177 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1179 "#ifdef USEVERTEXTEXTUREBLEND\n"
1180 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1181 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1182 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1183 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1185 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1188 "#ifdef USEDIFFUSE\n"
1189 " // get the surface normal and the gloss color\n"
1190 "# ifdef USEVERTEXTEXTUREBLEND\n"
1191 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1192 "# ifdef USESPECULAR\n"
1193 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1196 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1197 "# ifdef USESPECULAR\n"
1198 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1205 "#ifdef MODE_LIGHTSOURCE\n"
1206 " // light source\n"
1208 " // calculate surface normal, light normal, and specular normal\n"
1209 " // compute color intensity for the two textures (colormap and glossmap)\n"
1210 " // scale by light color and attenuation as efficiently as possible\n"
1211 " // (do as much scalar math as possible rather than vector math)\n"
1212 "# ifdef USEDIFFUSE\n"
1213 " // get the light normal\n"
1214 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1216 "# ifdef USESPECULAR\n"
1217 "# ifndef USEEXACTSPECULARMATH\n"
1218 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1221 " // calculate directional shading\n"
1222 "# ifdef USEEXACTSPECULARMATH\n"
1223 " 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"
1225 " 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"
1228 "# ifdef USEDIFFUSE\n"
1229 " // calculate directional shading\n"
1230 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1232 " // calculate directionless shading\n"
1233 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1237 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1238 "#if !showshadowmap\n"
1239 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1243 "# ifdef USECUBEFILTER\n"
1244 " // apply light cubemap filter\n"
1245 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1246 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1248 "#endif // MODE_LIGHTSOURCE\n"
1253 "#ifdef MODE_LIGHTDIRECTION\n"
1254 " // directional model lighting\n"
1255 "# ifdef USEDIFFUSE\n"
1256 " // get the light normal\n"
1257 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1259 "# ifdef USESPECULAR\n"
1260 " // calculate directional shading\n"
1261 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1262 "# ifdef USEEXACTSPECULARMATH\n"
1263 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1265 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1266 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1269 "# ifdef USEDIFFUSE\n"
1271 " // calculate directional shading\n"
1272 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1274 " color.rgb *= AmbientColor;\n"
1277 "#endif // MODE_LIGHTDIRECTION\n"
1282 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1283 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1285 " // get the light normal\n"
1286 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1287 " myhalf3 diffusenormal;\n"
1288 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1289 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1290 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1291 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1292 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1293 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1294 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1295 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1296 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1297 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1298 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1299 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1300 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1301 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1302 "# ifdef USESPECULAR\n"
1303 "# ifdef USEEXACTSPECULARMATH\n"
1304 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1306 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1307 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1311 " // apply lightmap color\n"
1312 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1313 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1318 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1319 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1321 " // get the light normal\n"
1322 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1323 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1324 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1325 "# ifdef USESPECULAR\n"
1326 "# ifdef USEEXACTSPECULARMATH\n"
1327 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1329 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1330 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1334 " // apply lightmap color\n"
1335 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1336 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1341 "#ifdef MODE_LIGHTMAP\n"
1342 " // apply lightmap color\n"
1343 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1344 "#endif // MODE_LIGHTMAP\n"
1349 "#ifdef MODE_VERTEXCOLOR\n"
1350 " // apply lightmap color\n"
1351 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1352 "#endif // MODE_VERTEXCOLOR\n"
1357 "#ifdef MODE_FLATCOLOR\n"
1358 "#endif // MODE_FLATCOLOR\n"
1366 " color *= TintColor;\n"
1369 "#ifdef USEVERTEXTEXTUREBLEND\n"
1370 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1372 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1376 " color.rgb *= SceneBrightness;\n"
1378 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1380 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1383 " // 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"
1384 "#ifdef USEREFLECTION\n"
1385 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1386 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1387 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1388 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1389 " // FIXME temporary hack to detect the case that the reflection\n"
1390 " // gets blackened at edges due to leaving the area that contains actual\n"
1392 " // Remove this 'ack once we have a better way to stop this thing from\n"
1394 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1395 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1396 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1397 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1398 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1399 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1402 " gl_FragColor = vec4(color);\n"
1404 "#if showshadowmap\n"
1405 "# ifdef USESHADOWMAPRECT\n"
1406 "# ifdef USESHADOWSAMPLER\n"
1407 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1409 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1412 "# ifdef USESHADOWMAP2D\n"
1413 "# ifdef USESHADOWSAMPLER\n"
1414 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1416 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1420 "# ifdef USESHADOWMAPCUBE\n"
1421 "# ifdef USESHADOWSAMPLER\n"
1422 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1424 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1429 "#endif // !MODE_REFRACTION\n"
1430 "#endif // !MODE_WATER\n"
1432 "#endif // FRAGMENT_SHADER\n"
1434 "#endif // !MODE_GENERIC\n"
1435 "#endif // !MODE_POSTPROCESS\n"
1436 "#endif // !MODE_SHOWDEPTH\n"
1437 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1440 typedef struct shaderpermutationinfo_s
1442 const char *pretext;
1445 shaderpermutationinfo_t;
1447 typedef struct shadermodeinfo_s
1449 const char *vertexfilename;
1450 const char *geometryfilename;
1451 const char *fragmentfilename;
1452 const char *pretext;
1457 typedef enum shaderpermutation_e
1459 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1460 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1461 SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
1462 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1463 SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
1464 SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
1465 SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
1466 SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
1467 SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
1468 SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
1469 SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
1470 SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
1471 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1472 SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1473 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
1474 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1475 SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
1476 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
1477 SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
1478 SHADERPERMUTATION_SHADOWMAPPCF = 1<<14, ///< (lightsource) use percentage closer filtering on shadowmap test results
1479 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<15, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1480 SHADERPERMUTATION_SHADOWSAMPLER = 1<<16, ///< (lightsource) use hardware shadowmap test
1481 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<17, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1482 SHADERPERMUTATION_LIMIT = 1<<18, ///< size of permutations array
1483 SHADERPERMUTATION_COUNT = 18 ///< size of shaderpermutationinfo array
1485 shaderpermutation_t;
1487 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1488 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1490 {"#define USEDIFFUSE\n", " diffuse"},
1491 {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
1492 {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
1493 {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
1494 {"#define USECUBEFILTER\n", " cubefilter"},
1495 {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
1496 {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
1497 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1498 {"#define USEREFLECTION\n", " reflection"},
1499 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1500 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1501 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1502 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1503 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1504 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1505 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1506 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1507 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1510 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1511 typedef enum shadermode_e
1513 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1514 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1515 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1516 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1517 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1518 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1519 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1520 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1521 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1522 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1523 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1524 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1525 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1530 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1531 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1533 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1534 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1535 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1536 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1537 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1538 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1539 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1540 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1541 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1542 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1543 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1544 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1545 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1548 struct r_glsl_permutation_s;
1549 typedef struct r_glsl_permutation_s
1551 /// hash lookup data
1552 struct r_glsl_permutation_s *hashnext;
1554 unsigned int permutation;
1556 /// indicates if we have tried compiling this permutation already
1558 /// 0 if compilation failed
1560 /// locations of detected uniforms in program object, or -1 if not found
1561 int loc_Texture_First;
1562 int loc_Texture_Second;
1563 int loc_Texture_GammaRamps;
1564 int loc_Texture_Normal;
1565 int loc_Texture_Color;
1566 int loc_Texture_Gloss;
1567 int loc_Texture_Glow;
1568 int loc_Texture_SecondaryNormal;
1569 int loc_Texture_SecondaryColor;
1570 int loc_Texture_SecondaryGloss;
1571 int loc_Texture_SecondaryGlow;
1572 int loc_Texture_Pants;
1573 int loc_Texture_Shirt;
1574 int loc_Texture_FogMask;
1575 int loc_Texture_Lightmap;
1576 int loc_Texture_Deluxemap;
1577 int loc_Texture_Attenuation;
1578 int loc_Texture_Cube;
1579 int loc_Texture_Refraction;
1580 int loc_Texture_Reflection;
1581 int loc_Texture_ShadowMapRect;
1582 int loc_Texture_ShadowMapCube;
1583 int loc_Texture_ShadowMap2D;
1584 int loc_Texture_CubeProjection;
1586 int loc_LightPosition;
1587 int loc_EyePosition;
1588 int loc_Color_Pants;
1589 int loc_Color_Shirt;
1590 int loc_FogRangeRecip;
1591 int loc_AmbientScale;
1592 int loc_DiffuseScale;
1593 int loc_SpecularScale;
1594 int loc_SpecularPower;
1596 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1597 int loc_OffsetMapping_Scale;
1599 int loc_AmbientColor;
1600 int loc_DiffuseColor;
1601 int loc_SpecularColor;
1603 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1604 int loc_GammaCoeff; ///< 1 / gamma
1605 int loc_DistortScaleRefractReflect;
1606 int loc_ScreenScaleRefractReflect;
1607 int loc_ScreenCenterRefractReflect;
1608 int loc_RefractColor;
1609 int loc_ReflectColor;
1610 int loc_ReflectFactor;
1611 int loc_ReflectOffset;
1619 int loc_ShadowMap_TextureScale;
1620 int loc_ShadowMap_Parameters;
1622 r_glsl_permutation_t;
1624 #define SHADERPERMUTATION_HASHSIZE 4096
1626 /// information about each possible shader permutation
1627 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1628 /// currently selected permutation
1629 r_glsl_permutation_t *r_glsl_permutation;
1630 /// storage for permutations linked in the hash table
1631 memexpandablearray_t r_glsl_permutationarray;
1633 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1635 //unsigned int hashdepth = 0;
1636 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1637 r_glsl_permutation_t *p;
1638 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1640 if (p->mode == mode && p->permutation == permutation)
1642 //if (hashdepth > 10)
1643 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1648 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1650 p->permutation = permutation;
1651 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1652 r_glsl_permutationhash[mode][hashindex] = p;
1653 //if (hashdepth > 10)
1654 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1658 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1661 if (!filename || !filename[0])
1663 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1666 if (printfromdisknotice)
1667 Con_DPrint("from disk... ");
1668 return shaderstring;
1670 else if (!strcmp(filename, "glsl/default.glsl"))
1672 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1673 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1675 return shaderstring;
1678 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1681 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1682 int vertstrings_count = 0;
1683 int geomstrings_count = 0;
1684 int fragstrings_count = 0;
1685 char *vertexstring, *geometrystring, *fragmentstring;
1686 const char *vertstrings_list[32+3];
1687 const char *geomstrings_list[32+3];
1688 const char *fragstrings_list[32+3];
1689 char permutationname[256];
1696 permutationname[0] = 0;
1697 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1698 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1699 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1701 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1703 // the first pretext is which type of shader to compile as
1704 // (later these will all be bound together as a program object)
1705 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1706 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1707 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1709 // the second pretext is the mode (for example a light source)
1710 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1711 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1712 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1713 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1715 // now add all the permutation pretexts
1716 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1718 if (permutation & (1<<i))
1720 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1721 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1722 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1723 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1727 // keep line numbers correct
1728 vertstrings_list[vertstrings_count++] = "\n";
1729 geomstrings_list[geomstrings_count++] = "\n";
1730 fragstrings_list[fragstrings_count++] = "\n";
1734 // now append the shader text itself
1735 vertstrings_list[vertstrings_count++] = vertexstring;
1736 geomstrings_list[geomstrings_count++] = geometrystring;
1737 fragstrings_list[fragstrings_count++] = fragmentstring;
1739 // if any sources were NULL, clear the respective list
1741 vertstrings_count = 0;
1742 if (!geometrystring)
1743 geomstrings_count = 0;
1744 if (!fragmentstring)
1745 fragstrings_count = 0;
1747 // compile the shader program
1748 if (vertstrings_count + geomstrings_count + fragstrings_count)
1749 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1753 qglUseProgramObjectARB(p->program);CHECKGLERROR
1754 // look up all the uniform variable names we care about, so we don't
1755 // have to look them up every time we set them
1756 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1757 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1758 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1759 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1760 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1761 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1762 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1763 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1764 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1765 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1766 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1767 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1768 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1769 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1770 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1771 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1772 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1773 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1774 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1775 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1776 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1777 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1778 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1779 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1780 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1781 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1782 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1783 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1784 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1785 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1786 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1787 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1788 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1789 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1790 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1791 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1792 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1793 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1794 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1795 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1796 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1797 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1798 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1799 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1800 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1801 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1802 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1803 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1804 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1805 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1806 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1807 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1808 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1809 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1810 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1811 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1812 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1813 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1814 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1815 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1816 // initialize the samplers to refer to the texture units we use
1817 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1818 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1819 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1820 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1821 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1822 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1823 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1824 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1825 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1826 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1827 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1828 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1829 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1830 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1831 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1832 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1833 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1834 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1835 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1836 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1837 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1838 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1839 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1840 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1842 if (developer.integer)
1843 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1846 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1850 Mem_Free(vertexstring);
1852 Mem_Free(geometrystring);
1854 Mem_Free(fragmentstring);
1857 void R_GLSL_Restart_f(void)
1859 unsigned int i, limit;
1860 r_glsl_permutation_t *p;
1861 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1862 for (i = 0;i < limit;i++)
1864 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1866 GL_Backend_FreeProgram(p->program);
1867 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1870 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1873 void R_GLSL_DumpShader_f(void)
1877 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1880 Con_Printf("failed to write to glsl/default.glsl\n");
1884 FS_Print(file, "/* The engine may define the following macros:\n");
1885 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1886 for (i = 0;i < SHADERMODE_COUNT;i++)
1887 FS_Print(file, shadermodeinfo[i].pretext);
1888 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1889 FS_Print(file, shaderpermutationinfo[i].pretext);
1890 FS_Print(file, "*/\n");
1891 FS_Print(file, builtinshaderstring);
1894 Con_Printf("glsl/default.glsl written\n");
1897 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1899 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1900 if (r_glsl_permutation != perm)
1902 r_glsl_permutation = perm;
1903 if (!r_glsl_permutation->program)
1905 if (!r_glsl_permutation->compiled)
1906 R_GLSL_CompilePermutation(perm, mode, permutation);
1907 if (!r_glsl_permutation->program)
1909 // remove features until we find a valid permutation
1911 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1913 // reduce i more quickly whenever it would not remove any bits
1914 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1915 if (!(permutation & j))
1918 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1919 if (!r_glsl_permutation->compiled)
1920 R_GLSL_CompilePermutation(perm, mode, permutation);
1921 if (r_glsl_permutation->program)
1924 if (i >= SHADERPERMUTATION_COUNT)
1926 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");
1927 Cvar_SetValueQuick(&r_glsl, 0);
1928 R_GLSL_Restart_f(); // unload shaders
1929 return; // no bit left to clear
1934 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1938 void R_SetupGenericShader(qboolean usetexture)
1940 if (gl_support_fragment_shader)
1942 if (r_glsl.integer && r_glsl_usegeneric.integer)
1943 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1944 else if (r_glsl_permutation)
1946 r_glsl_permutation = NULL;
1947 qglUseProgramObjectARB(0);CHECKGLERROR
1952 void R_SetupGenericTwoTextureShader(int texturemode)
1954 if (gl_support_fragment_shader)
1956 if (r_glsl.integer && r_glsl_usegeneric.integer)
1957 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))));
1958 else if (r_glsl_permutation)
1960 r_glsl_permutation = NULL;
1961 qglUseProgramObjectARB(0);CHECKGLERROR
1964 if (!r_glsl_permutation)
1966 if (texturemode == GL_DECAL && gl_combine.integer)
1967 texturemode = GL_INTERPOLATE_ARB;
1968 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1972 void R_SetupDepthOrShadowShader(void)
1974 if (gl_support_fragment_shader)
1976 if (r_glsl.integer && r_glsl_usegeneric.integer)
1977 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1978 else if (r_glsl_permutation)
1980 r_glsl_permutation = NULL;
1981 qglUseProgramObjectARB(0);CHECKGLERROR
1986 void R_SetupShowDepthShader(void)
1988 if (gl_support_fragment_shader)
1990 if (r_glsl.integer && r_glsl_usegeneric.integer)
1991 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
1992 else if (r_glsl_permutation)
1994 r_glsl_permutation = NULL;
1995 qglUseProgramObjectARB(0);CHECKGLERROR
2000 extern rtexture_t *r_shadow_attenuationgradienttexture;
2001 extern rtexture_t *r_shadow_attenuation2dtexture;
2002 extern rtexture_t *r_shadow_attenuation3dtexture;
2003 extern qboolean r_shadow_usingshadowmaprect;
2004 extern qboolean r_shadow_usingshadowmapcube;
2005 extern qboolean r_shadow_usingshadowmap2d;
2006 extern float r_shadow_shadowmap_texturescale[2];
2007 extern float r_shadow_shadowmap_parameters[4];
2008 extern qboolean r_shadow_shadowmapvsdct;
2009 extern qboolean r_shadow_shadowmapsampler;
2010 extern int r_shadow_shadowmappcf;
2011 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2013 // select a permutation of the lighting shader appropriate to this
2014 // combination of texture, entity, light source, and fogging, only use the
2015 // minimum features necessary to avoid wasting rendering time in the
2016 // fragment shader on features that are not being used
2017 unsigned int permutation = 0;
2018 unsigned int mode = 0;
2019 // TODO: implement geometry-shader based shadow volumes someday
2020 if (r_glsl_offsetmapping.integer)
2022 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2023 if (r_glsl_offsetmapping_reliefmapping.integer)
2024 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2026 if (rsurfacepass == RSURFPASS_BACKGROUND)
2028 // distorted background
2029 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2030 mode = SHADERMODE_WATER;
2032 mode = SHADERMODE_REFRACTION;
2034 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2037 mode = SHADERMODE_LIGHTSOURCE;
2038 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2039 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2040 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2041 permutation |= SHADERPERMUTATION_CUBEFILTER;
2042 if (diffusescale > 0)
2043 permutation |= SHADERPERMUTATION_DIFFUSE;
2044 if (specularscale > 0)
2045 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2046 if (r_refdef.fogenabled)
2047 permutation |= SHADERPERMUTATION_FOG;
2048 if (rsurface.texture->colormapping)
2049 permutation |= SHADERPERMUTATION_COLORMAPPING;
2050 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2052 if (r_shadow_usingshadowmaprect)
2053 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2054 if (r_shadow_usingshadowmap2d)
2055 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2056 if (r_shadow_usingshadowmapcube)
2057 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2058 else if(r_shadow_shadowmapvsdct)
2059 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2061 if (r_shadow_shadowmapsampler)
2062 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2063 if (r_shadow_shadowmappcf > 1)
2064 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2065 else if (r_shadow_shadowmappcf)
2066 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2069 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2071 // unshaded geometry (fullbright or ambient model lighting)
2072 mode = SHADERMODE_FLATCOLOR;
2073 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2074 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2075 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2076 permutation |= SHADERPERMUTATION_GLOW;
2077 if (r_refdef.fogenabled)
2078 permutation |= SHADERPERMUTATION_FOG;
2079 if (rsurface.texture->colormapping)
2080 permutation |= SHADERPERMUTATION_COLORMAPPING;
2081 if (r_glsl_offsetmapping.integer)
2083 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2084 if (r_glsl_offsetmapping_reliefmapping.integer)
2085 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2087 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2088 permutation |= SHADERPERMUTATION_REFLECTION;
2090 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2092 // directional model lighting
2093 mode = SHADERMODE_LIGHTDIRECTION;
2094 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2095 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2096 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2097 permutation |= SHADERPERMUTATION_GLOW;
2098 permutation |= SHADERPERMUTATION_DIFFUSE;
2099 if (specularscale > 0)
2100 permutation |= SHADERPERMUTATION_SPECULAR;
2101 if (r_refdef.fogenabled)
2102 permutation |= SHADERPERMUTATION_FOG;
2103 if (rsurface.texture->colormapping)
2104 permutation |= SHADERPERMUTATION_COLORMAPPING;
2105 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2106 permutation |= SHADERPERMUTATION_REFLECTION;
2108 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2110 // ambient model lighting
2111 mode = SHADERMODE_LIGHTDIRECTION;
2112 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2113 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2114 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2115 permutation |= SHADERPERMUTATION_GLOW;
2116 if (r_refdef.fogenabled)
2117 permutation |= SHADERPERMUTATION_FOG;
2118 if (rsurface.texture->colormapping)
2119 permutation |= SHADERPERMUTATION_COLORMAPPING;
2120 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2121 permutation |= SHADERPERMUTATION_REFLECTION;
2126 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2128 // deluxemapping (light direction texture)
2129 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2130 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2132 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2133 permutation |= SHADERPERMUTATION_DIFFUSE;
2134 if (specularscale > 0)
2135 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2137 else if (r_glsl_deluxemapping.integer >= 2)
2139 // fake deluxemapping (uniform light direction in tangentspace)
2140 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2141 permutation |= SHADERPERMUTATION_DIFFUSE;
2142 if (specularscale > 0)
2143 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2145 else if (rsurface.uselightmaptexture)
2147 // ordinary lightmapping (q1bsp, q3bsp)
2148 mode = SHADERMODE_LIGHTMAP;
2152 // ordinary vertex coloring (q3bsp)
2153 mode = SHADERMODE_VERTEXCOLOR;
2155 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2156 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2157 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2158 permutation |= SHADERPERMUTATION_GLOW;
2159 if (r_refdef.fogenabled)
2160 permutation |= SHADERPERMUTATION_FOG;
2161 if (rsurface.texture->colormapping)
2162 permutation |= SHADERPERMUTATION_COLORMAPPING;
2163 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2164 permutation |= SHADERPERMUTATION_REFLECTION;
2166 if(permutation & SHADERPERMUTATION_SPECULAR)
2167 if(r_shadow_glossexact.integer)
2168 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2169 R_SetupShader_SetPermutation(mode, permutation);
2170 if (mode == SHADERMODE_LIGHTSOURCE)
2172 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2173 if (permutation & SHADERPERMUTATION_DIFFUSE)
2175 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2176 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2177 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2178 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2182 // ambient only is simpler
2183 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]);
2184 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2185 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2186 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2188 // additive passes are only darkened by fog, not tinted
2189 if (r_glsl_permutation->loc_FogColor >= 0)
2190 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2191 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]);
2192 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]);
2196 if (mode == SHADERMODE_LIGHTDIRECTION)
2198 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);
2199 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);
2200 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);
2201 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]);
2205 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2206 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2207 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2209 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]);
2210 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);
2211 // additive passes are only darkened by fog, not tinted
2212 if (r_glsl_permutation->loc_FogColor >= 0)
2214 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2215 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2217 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2219 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);
2220 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]);
2221 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]);
2222 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2223 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2224 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2225 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2227 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2228 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2229 if (r_glsl_permutation->loc_Color_Pants >= 0)
2231 if (rsurface.texture->currentskinframe->pants)
2232 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2234 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2236 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2238 if (rsurface.texture->currentskinframe->shirt)
2239 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2241 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2243 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
2244 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2246 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2250 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2252 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2256 #define SKINFRAME_HASH 1024
2260 int loadsequence; // incremented each level change
2261 memexpandablearray_t array;
2262 skinframe_t *hash[SKINFRAME_HASH];
2265 r_skinframe_t r_skinframe;
2267 void R_SkinFrame_PrepareForPurge(void)
2269 r_skinframe.loadsequence++;
2270 // wrap it without hitting zero
2271 if (r_skinframe.loadsequence >= 200)
2272 r_skinframe.loadsequence = 1;
2275 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2279 // mark the skinframe as used for the purging code
2280 skinframe->loadsequence = r_skinframe.loadsequence;
2283 void R_SkinFrame_Purge(void)
2287 for (i = 0;i < SKINFRAME_HASH;i++)
2289 for (s = r_skinframe.hash[i];s;s = s->next)
2291 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2293 if (s->merged == s->base)
2295 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2296 R_PurgeTexture(s->stain );s->stain = NULL;
2297 R_PurgeTexture(s->merged);s->merged = NULL;
2298 R_PurgeTexture(s->base );s->base = NULL;
2299 R_PurgeTexture(s->pants );s->pants = NULL;
2300 R_PurgeTexture(s->shirt );s->shirt = NULL;
2301 R_PurgeTexture(s->nmap );s->nmap = NULL;
2302 R_PurgeTexture(s->gloss );s->gloss = NULL;
2303 R_PurgeTexture(s->glow );s->glow = NULL;
2304 R_PurgeTexture(s->fog );s->fog = NULL;
2305 s->loadsequence = 0;
2311 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2313 char basename[MAX_QPATH];
2315 Image_StripImageExtension(name, basename, sizeof(basename));
2317 if( last == NULL ) {
2319 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2320 item = r_skinframe.hash[hashindex];
2325 // linearly search through the hash bucket
2326 for( ; item ; item = item->next ) {
2327 if( !strcmp( item->basename, basename ) ) {
2334 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2338 char basename[MAX_QPATH];
2340 Image_StripImageExtension(name, basename, sizeof(basename));
2342 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2343 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2344 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2348 rtexture_t *dyntexture;
2349 // check whether its a dynamic texture
2350 dyntexture = CL_GetDynTexture( basename );
2351 if (!add && !dyntexture)
2353 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2354 memset(item, 0, sizeof(*item));
2355 strlcpy(item->basename, basename, sizeof(item->basename));
2356 item->base = dyntexture; // either NULL or dyntexture handle
2357 item->textureflags = textureflags;
2358 item->comparewidth = comparewidth;
2359 item->compareheight = compareheight;
2360 item->comparecrc = comparecrc;
2361 item->next = r_skinframe.hash[hashindex];
2362 r_skinframe.hash[hashindex] = item;
2364 else if( item->base == NULL )
2366 rtexture_t *dyntexture;
2367 // check whether its a dynamic texture
2368 // 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]
2369 dyntexture = CL_GetDynTexture( basename );
2370 item->base = dyntexture; // either NULL or dyntexture handle
2373 R_SkinFrame_MarkUsed(item);
2377 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2379 unsigned long long avgcolor[5], wsum; \
2387 for(pix = 0; pix < cnt; ++pix) \
2390 for(comp = 0; comp < 3; ++comp) \
2392 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2395 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2397 for(comp = 0; comp < 3; ++comp) \
2398 avgcolor[comp] += getpixel * w; \
2401 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2402 avgcolor[4] += getpixel; \
2404 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2406 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2407 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2408 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2409 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2412 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2414 // FIXME: it should be possible to disable loading various layers using
2415 // cvars, to prevent wasted loading time and memory usage if the user does
2417 qboolean loadnormalmap = true;
2418 qboolean loadgloss = true;
2419 qboolean loadpantsandshirt = true;
2420 qboolean loadglow = true;
2422 unsigned char *pixels;
2423 unsigned char *bumppixels;
2424 unsigned char *basepixels = NULL;
2425 int basepixels_width;
2426 int basepixels_height;
2427 skinframe_t *skinframe;
2432 if (cls.state == ca_dedicated)
2435 // return an existing skinframe if already loaded
2436 // if loading of the first image fails, don't make a new skinframe as it
2437 // would cause all future lookups of this to be missing
2438 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2439 if (skinframe && skinframe->base)
2442 basepixels = loadimagepixelsbgra(name, complain, true);
2443 if (basepixels == NULL)
2446 if (developer_loading.integer)
2447 Con_Printf("loading skin \"%s\"\n", name);
2449 // we've got some pixels to store, so really allocate this new texture now
2451 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2452 skinframe->stain = NULL;
2453 skinframe->merged = NULL;
2454 skinframe->base = r_texture_notexture;
2455 skinframe->pants = NULL;
2456 skinframe->shirt = NULL;
2457 skinframe->nmap = r_texture_blanknormalmap;
2458 skinframe->gloss = NULL;
2459 skinframe->glow = NULL;
2460 skinframe->fog = NULL;
2462 basepixels_width = image_width;
2463 basepixels_height = image_height;
2464 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);
2466 if (textureflags & TEXF_ALPHA)
2468 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2469 if (basepixels[j] < 255)
2471 if (j < basepixels_width * basepixels_height * 4)
2473 // has transparent pixels
2476 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2477 for (j = 0;j < image_width * image_height * 4;j += 4)
2482 pixels[j+3] = basepixels[j+3];
2484 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);
2489 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2490 //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]);
2492 // _norm is the name used by tenebrae and has been adopted as standard
2495 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2497 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);
2501 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2503 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2504 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2505 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);
2507 Mem_Free(bumppixels);
2509 else if (r_shadow_bumpscale_basetexture.value > 0)
2511 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2512 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2513 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);
2517 // _luma is supported for tenebrae compatibility
2518 // (I think it's a very stupid name, but oh well)
2519 // _glow is the preferred name
2520 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;}
2521 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;}
2522 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;}
2523 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;}
2526 Mem_Free(basepixels);
2531 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2533 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL);
2536 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)
2541 for (i = 0;i < width*height;i++)
2542 if (((unsigned char *)&palette[in[i]])[3] > 0)
2544 if (i == width*height)
2547 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2550 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2551 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2554 unsigned char *temp1, *temp2;
2555 skinframe_t *skinframe;
2557 if (cls.state == ca_dedicated)
2560 // if already loaded just return it, otherwise make a new skinframe
2561 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2562 if (skinframe && skinframe->base)
2565 skinframe->stain = NULL;
2566 skinframe->merged = NULL;
2567 skinframe->base = r_texture_notexture;
2568 skinframe->pants = NULL;
2569 skinframe->shirt = NULL;
2570 skinframe->nmap = r_texture_blanknormalmap;
2571 skinframe->gloss = NULL;
2572 skinframe->glow = NULL;
2573 skinframe->fog = NULL;
2575 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2579 if (developer_loading.integer)
2580 Con_Printf("loading 32bit skin \"%s\"\n", name);
2582 if (r_shadow_bumpscale_basetexture.value > 0)
2584 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2585 temp2 = temp1 + width * height * 4;
2586 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2587 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2590 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2591 if (textureflags & TEXF_ALPHA)
2593 for (i = 3;i < width * height * 4;i += 4)
2594 if (skindata[i] < 255)
2596 if (i < width * height * 4)
2598 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2599 memcpy(fogpixels, skindata, width * height * 4);
2600 for (i = 0;i < width * height * 4;i += 4)
2601 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2602 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2603 Mem_Free(fogpixels);
2607 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2608 //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]);
2613 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2616 unsigned char *temp1, *temp2;
2617 unsigned int *palette;
2618 skinframe_t *skinframe;
2620 if (cls.state == ca_dedicated)
2623 // if already loaded just return it, otherwise make a new skinframe
2624 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2625 if (skinframe && skinframe->base)
2628 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2630 skinframe->stain = NULL;
2631 skinframe->merged = NULL;
2632 skinframe->base = r_texture_notexture;
2633 skinframe->pants = NULL;
2634 skinframe->shirt = NULL;
2635 skinframe->nmap = r_texture_blanknormalmap;
2636 skinframe->gloss = NULL;
2637 skinframe->glow = NULL;
2638 skinframe->fog = NULL;
2640 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2644 if (developer_loading.integer)
2645 Con_Printf("loading quake skin \"%s\"\n", name);
2647 if (r_shadow_bumpscale_basetexture.value > 0)
2649 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2650 temp2 = temp1 + width * height * 4;
2651 // use either a custom palette or the quake palette
2652 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2653 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2654 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2657 // use either a custom palette, or the quake palette
2658 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2659 if (loadglowtexture)
2660 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2661 if (loadpantsandshirt)
2663 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2664 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2666 if (skinframe->pants || skinframe->shirt)
2667 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
2668 if (textureflags & TEXF_ALPHA)
2670 for (i = 0;i < width * height;i++)
2671 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2673 if (i < width * height)
2674 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2677 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2678 //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]);
2683 skinframe_t *R_SkinFrame_LoadMissing(void)
2685 skinframe_t *skinframe;
2687 if (cls.state == ca_dedicated)
2690 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2691 skinframe->stain = NULL;
2692 skinframe->merged = NULL;
2693 skinframe->base = r_texture_notexture;
2694 skinframe->pants = NULL;
2695 skinframe->shirt = NULL;
2696 skinframe->nmap = r_texture_blanknormalmap;
2697 skinframe->gloss = NULL;
2698 skinframe->glow = NULL;
2699 skinframe->fog = NULL;
2701 skinframe->avgcolor[0] = rand() / RAND_MAX;
2702 skinframe->avgcolor[1] = rand() / RAND_MAX;
2703 skinframe->avgcolor[2] = rand() / RAND_MAX;
2704 skinframe->avgcolor[3] = 1;
2709 void gl_main_start(void)
2713 memset(r_queries, 0, sizeof(r_queries));
2715 r_qwskincache = NULL;
2716 r_qwskincache_size = 0;
2718 // set up r_skinframe loading system for textures
2719 memset(&r_skinframe, 0, sizeof(r_skinframe));
2720 r_skinframe.loadsequence = 1;
2721 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2723 r_main_texturepool = R_AllocTexturePool();
2724 R_BuildBlankTextures();
2726 if (gl_texturecubemap)
2729 R_BuildNormalizationCube();
2731 r_texture_fogattenuation = NULL;
2732 r_texture_gammaramps = NULL;
2733 //r_texture_fogintensity = NULL;
2734 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2735 memset(&r_waterstate, 0, sizeof(r_waterstate));
2736 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2737 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2738 memset(&r_svbsp, 0, sizeof (r_svbsp));
2740 r_refdef.fogmasktable_density = 0;
2743 extern rtexture_t *loadingscreentexture;
2744 void gl_main_shutdown(void)
2747 qglDeleteQueriesARB(r_maxqueries, r_queries);
2751 memset(r_queries, 0, sizeof(r_queries));
2753 r_qwskincache = NULL;
2754 r_qwskincache_size = 0;
2756 // clear out the r_skinframe state
2757 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2758 memset(&r_skinframe, 0, sizeof(r_skinframe));
2761 Mem_Free(r_svbsp.nodes);
2762 memset(&r_svbsp, 0, sizeof (r_svbsp));
2763 R_FreeTexturePool(&r_main_texturepool);
2764 loadingscreentexture = NULL;
2765 r_texture_blanknormalmap = NULL;
2766 r_texture_white = NULL;
2767 r_texture_grey128 = NULL;
2768 r_texture_black = NULL;
2769 r_texture_whitecube = NULL;
2770 r_texture_normalizationcube = NULL;
2771 r_texture_fogattenuation = NULL;
2772 r_texture_gammaramps = NULL;
2773 //r_texture_fogintensity = NULL;
2774 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2775 memset(&r_waterstate, 0, sizeof(r_waterstate));
2779 extern void CL_ParseEntityLump(char *entitystring);
2780 void gl_main_newmap(void)
2782 // FIXME: move this code to client
2784 char *entities, entname[MAX_QPATH];
2786 Mem_Free(r_qwskincache);
2787 r_qwskincache = NULL;
2788 r_qwskincache_size = 0;
2791 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2792 l = (int)strlen(entname) - 4;
2793 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2795 memcpy(entname + l, ".ent", 5);
2796 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2798 CL_ParseEntityLump(entities);
2803 if (cl.worldmodel->brush.entities)
2804 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2808 void GL_Main_Init(void)
2810 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2812 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2813 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2814 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2815 if (gamemode == GAME_NEHAHRA)
2817 Cvar_RegisterVariable (&gl_fogenable);
2818 Cvar_RegisterVariable (&gl_fogdensity);
2819 Cvar_RegisterVariable (&gl_fogred);
2820 Cvar_RegisterVariable (&gl_foggreen);
2821 Cvar_RegisterVariable (&gl_fogblue);
2822 Cvar_RegisterVariable (&gl_fogstart);
2823 Cvar_RegisterVariable (&gl_fogend);
2824 Cvar_RegisterVariable (&gl_skyclip);
2826 Cvar_RegisterVariable(&r_motionblur);
2827 Cvar_RegisterVariable(&r_motionblur_maxblur);
2828 Cvar_RegisterVariable(&r_motionblur_bmin);
2829 Cvar_RegisterVariable(&r_motionblur_vmin);
2830 Cvar_RegisterVariable(&r_motionblur_vmax);
2831 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2832 Cvar_RegisterVariable(&r_motionblur_randomize);
2833 Cvar_RegisterVariable(&r_damageblur);
2834 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
2835 Cvar_RegisterVariable(&r_equalize_entities_by);
2836 Cvar_RegisterVariable(&r_equalize_entities_to);
2837 Cvar_RegisterVariable(&r_animcache);
2838 Cvar_RegisterVariable(&r_depthfirst);
2839 Cvar_RegisterVariable(&r_useinfinitefarclip);
2840 Cvar_RegisterVariable(&r_nearclip);
2841 Cvar_RegisterVariable(&r_showbboxes);
2842 Cvar_RegisterVariable(&r_showsurfaces);
2843 Cvar_RegisterVariable(&r_showtris);
2844 Cvar_RegisterVariable(&r_shownormals);
2845 Cvar_RegisterVariable(&r_showlighting);
2846 Cvar_RegisterVariable(&r_showshadowvolumes);
2847 Cvar_RegisterVariable(&r_showcollisionbrushes);
2848 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2849 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2850 Cvar_RegisterVariable(&r_showdisabledepthtest);
2851 Cvar_RegisterVariable(&r_drawportals);
2852 Cvar_RegisterVariable(&r_drawentities);
2853 Cvar_RegisterVariable(&r_cullentities_trace);
2854 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2855 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2856 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2857 Cvar_RegisterVariable(&r_drawviewmodel);
2858 Cvar_RegisterVariable(&r_speeds);
2859 Cvar_RegisterVariable(&r_fullbrights);
2860 Cvar_RegisterVariable(&r_wateralpha);
2861 Cvar_RegisterVariable(&r_dynamic);
2862 Cvar_RegisterVariable(&r_fullbright);
2863 Cvar_RegisterVariable(&r_shadows);
2864 Cvar_RegisterVariable(&r_shadows_darken);
2865 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
2866 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2867 Cvar_RegisterVariable(&r_shadows_throwdistance);
2868 Cvar_RegisterVariable(&r_shadows_throwdirection);
2869 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2870 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2871 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2872 Cvar_RegisterVariable(&r_fog_exp2);
2873 Cvar_RegisterVariable(&r_drawfog);
2874 Cvar_RegisterVariable(&r_textureunits);
2875 Cvar_RegisterVariable(&r_glsl);
2876 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2877 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2878 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2879 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2880 Cvar_RegisterVariable(&r_glsl_postprocess);
2881 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2882 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2883 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2884 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2885 Cvar_RegisterVariable(&r_glsl_usegeneric);
2886 Cvar_RegisterVariable(&r_water);
2887 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2888 Cvar_RegisterVariable(&r_water_clippingplanebias);
2889 Cvar_RegisterVariable(&r_water_refractdistort);
2890 Cvar_RegisterVariable(&r_water_reflectdistort);
2891 Cvar_RegisterVariable(&r_lerpsprites);
2892 Cvar_RegisterVariable(&r_lerpmodels);
2893 Cvar_RegisterVariable(&r_lerplightstyles);
2894 Cvar_RegisterVariable(&r_waterscroll);
2895 Cvar_RegisterVariable(&r_bloom);
2896 Cvar_RegisterVariable(&r_bloom_colorscale);
2897 Cvar_RegisterVariable(&r_bloom_brighten);
2898 Cvar_RegisterVariable(&r_bloom_blur);
2899 Cvar_RegisterVariable(&r_bloom_resolution);
2900 Cvar_RegisterVariable(&r_bloom_colorexponent);
2901 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2902 Cvar_RegisterVariable(&r_hdr);
2903 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2904 Cvar_RegisterVariable(&r_hdr_glowintensity);
2905 Cvar_RegisterVariable(&r_hdr_range);
2906 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2907 Cvar_RegisterVariable(&developer_texturelogging);
2908 Cvar_RegisterVariable(&gl_lightmaps);
2909 Cvar_RegisterVariable(&r_test);
2910 Cvar_RegisterVariable(&r_batchmode);
2911 Cvar_RegisterVariable(&r_glsl_saturation);
2912 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2913 Cvar_SetValue("r_fullbrights", 0);
2914 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2916 Cvar_RegisterVariable(&r_track_sprites);
2917 Cvar_RegisterVariable(&r_track_sprites_flags);
2918 Cvar_RegisterVariable(&r_track_sprites_scalew);
2919 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2922 extern void R_Textures_Init(void);
2923 extern void GL_Draw_Init(void);
2924 extern void GL_Main_Init(void);
2925 extern void R_Shadow_Init(void);
2926 extern void R_Sky_Init(void);
2927 extern void GL_Surf_Init(void);
2928 extern void R_Particles_Init(void);
2929 extern void R_Explosion_Init(void);
2930 extern void gl_backend_init(void);
2931 extern void Sbar_Init(void);
2932 extern void R_LightningBeams_Init(void);
2933 extern void Mod_RenderInit(void);
2935 void Render_Init(void)
2947 R_LightningBeams_Init();
2956 extern char *ENGINE_EXTENSIONS;
2959 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2960 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2961 gl_version = (const char *)qglGetString(GL_VERSION);
2962 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2966 if (!gl_platformextensions)
2967 gl_platformextensions = "";
2969 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2970 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2971 Con_Printf("GL_VERSION: %s\n", gl_version);
2972 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2973 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2975 VID_CheckExtensions();
2977 // LordHavoc: report supported extensions
2978 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2980 // clear to black (loading plaque will be seen over this)
2982 qglClearColor(0,0,0,1);CHECKGLERROR
2983 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2986 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2990 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2992 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2995 p = r_refdef.view.frustum + i;
3000 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3004 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3008 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3012 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3016 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3020 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3024 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3028 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3036 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3040 for (i = 0;i < numplanes;i++)
3047 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3051 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3055 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3059 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3063 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3067 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3071 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3075 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3083 //==================================================================================
3085 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3088 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3089 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3090 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3093 typedef struct r_animcache_entity_s
3100 qboolean wantnormals;
3101 qboolean wanttangents;
3103 r_animcache_entity_t;
3105 typedef struct r_animcache_s
3107 r_animcache_entity_t entity[MAX_EDICTS*2];
3113 static r_animcache_t r_animcachestate;
3115 void R_AnimCache_Free(void)
3118 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3120 r_animcachestate.entity[idx].maxvertices = 0;
3121 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3122 r_animcachestate.entity[idx].vertex3f = NULL;
3123 r_animcachestate.entity[idx].normal3f = NULL;
3124 r_animcachestate.entity[idx].svector3f = NULL;
3125 r_animcachestate.entity[idx].tvector3f = NULL;
3127 r_animcachestate.currentindex = 0;
3128 r_animcachestate.maxindex = 0;
3131 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3135 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3137 if (cache->maxvertices >= numvertices)
3140 // Release existing memory
3141 if (cache->vertex3f)
3142 Mem_Free(cache->vertex3f);
3144 // Pad by 1024 verts
3145 cache->maxvertices = (numvertices + 1023) & ~1023;
3146 arraySize = cache->maxvertices * 3;
3148 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3149 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3150 r_animcachestate.entity[cacheIdx].vertex3f = base;
3151 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3152 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3153 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3155 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3158 void R_AnimCache_NewFrame(void)
3162 if (r_animcache.integer && r_drawentities.integer)
3163 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3164 else if (r_animcachestate.maxindex)
3167 r_animcachestate.currentindex = 0;
3169 for (i = 0;i < r_refdef.scene.numentities;i++)
3170 r_refdef.scene.entities[i]->animcacheindex = -1;
3173 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3175 dp_model_t *model = ent->model;
3176 r_animcache_entity_t *c;
3177 // see if it's already cached this frame
3178 if (ent->animcacheindex >= 0)
3180 // add normals/tangents if needed
3181 c = r_animcachestate.entity + ent->animcacheindex;
3183 wantnormals = false;
3184 if (c->wanttangents)
3185 wanttangents = false;
3186 if (wantnormals || wanttangents)
3187 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3191 // see if this ent is worth caching
3192 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3194 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3196 // assign it a cache entry and make sure the arrays are big enough
3197 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3198 ent->animcacheindex = r_animcachestate.currentindex++;
3199 c = r_animcachestate.entity + ent->animcacheindex;
3200 c->wantnormals = wantnormals;
3201 c->wanttangents = wanttangents;
3202 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3207 void R_AnimCache_CacheVisibleEntities(void)
3210 qboolean wantnormals;
3211 qboolean wanttangents;
3213 if (!r_animcachestate.maxindex)
3216 wantnormals = !r_showsurfaces.integer;
3217 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3219 // TODO: thread this?
3221 for (i = 0;i < r_refdef.scene.numentities;i++)
3223 if (!r_refdef.viewcache.entityvisible[i])
3225 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3229 //==================================================================================
3231 static void R_View_UpdateEntityLighting (void)
3234 entity_render_t *ent;
3235 vec3_t tempdiffusenormal, avg;
3238 for (i = 0;i < r_refdef.scene.numentities;i++)
3240 ent = r_refdef.scene.entities[i];
3242 // skip unseen models
3243 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3247 if (ent->model && ent->model->brush.num_leafs)
3249 // TODO: use modellight for r_ambient settings on world?
3250 VectorSet(ent->modellight_ambient, 0, 0, 0);
3251 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3252 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3256 // fetch the lighting from the worldmodel data
3257 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));
3258 VectorClear(ent->modellight_diffuse);
3259 VectorClear(tempdiffusenormal);
3260 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3263 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3264 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3265 if(r_equalize_entities_by.value != 0 && r_equalize_entities_to.value != 0 && (ent->flags & RENDER_EQUALIZE))
3267 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3268 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3271 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3272 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3273 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3278 VectorSet(ent->modellight_ambient, 1, 1, 1);
3280 // move the light direction into modelspace coordinates for lighting code
3281 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3282 if(VectorLength2(ent->modellight_lightdir) == 0)
3283 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3284 VectorNormalize(ent->modellight_lightdir);
3288 #define MAX_LINEOFSIGHTTRACES 64
3290 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3293 vec3_t boxmins, boxmaxs;
3296 dp_model_t *model = r_refdef.scene.worldmodel;
3298 if (!model || !model->brush.TraceLineOfSight)
3301 // expand the box a little
3302 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3303 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3304 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3305 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3306 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3307 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3310 VectorCopy(eye, start);
3311 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3312 if (model->brush.TraceLineOfSight(model, start, end))
3315 // try various random positions
3316 for (i = 0;i < numsamples;i++)
3318 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3319 if (model->brush.TraceLineOfSight(model, start, end))
3327 static void R_View_UpdateEntityVisible (void)
3330 entity_render_t *ent;
3332 if (!r_drawentities.integer)
3335 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3336 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3338 // worldmodel can check visibility
3339 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3340 for (i = 0;i < r_refdef.scene.numentities;i++)
3342 ent = r_refdef.scene.entities[i];
3343 if (!(ent->flags & renderimask))
3344 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)))
3345 if ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
3346 r_refdef.viewcache.entityvisible[i] = true;
3348 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3350 for (i = 0;i < r_refdef.scene.numentities;i++)
3352 ent = r_refdef.scene.entities[i];
3353 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & (RENDER_VIEWMODEL + RENDER_NOCULL)) && !(ent->model && (ent->model->name[0] == '*')))
3355 if(R_CanSeeBox(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3356 ent->last_trace_visibility = realtime;
3357 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3358 r_refdef.viewcache.entityvisible[i] = 0;
3365 // no worldmodel or it can't check visibility
3366 for (i = 0;i < r_refdef.scene.numentities;i++)
3368 ent = r_refdef.scene.entities[i];
3369 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));
3374 /// only used if skyrendermasked, and normally returns false
3375 int R_DrawBrushModelsSky (void)
3378 entity_render_t *ent;
3380 if (!r_drawentities.integer)
3384 for (i = 0;i < r_refdef.scene.numentities;i++)
3386 if (!r_refdef.viewcache.entityvisible[i])
3388 ent = r_refdef.scene.entities[i];
3389 if (!ent->model || !ent->model->DrawSky)
3391 ent->model->DrawSky(ent);
3397 static void R_DrawNoModel(entity_render_t *ent);
3398 static void R_DrawModels(void)
3401 entity_render_t *ent;
3403 if (!r_drawentities.integer)
3406 for (i = 0;i < r_refdef.scene.numentities;i++)
3408 if (!r_refdef.viewcache.entityvisible[i])
3410 ent = r_refdef.scene.entities[i];
3411 r_refdef.stats.entities++;
3412 if (ent->model && ent->model->Draw != NULL)
3413 ent->model->Draw(ent);
3419 static void R_DrawModelsDepth(void)
3422 entity_render_t *ent;
3424 if (!r_drawentities.integer)
3427 for (i = 0;i < r_refdef.scene.numentities;i++)
3429 if (!r_refdef.viewcache.entityvisible[i])
3431 ent = r_refdef.scene.entities[i];
3432 if (ent->model && ent->model->DrawDepth != NULL)
3433 ent->model->DrawDepth(ent);
3437 static void R_DrawModelsDebug(void)
3440 entity_render_t *ent;
3442 if (!r_drawentities.integer)
3445 for (i = 0;i < r_refdef.scene.numentities;i++)
3447 if (!r_refdef.viewcache.entityvisible[i])
3449 ent = r_refdef.scene.entities[i];
3450 if (ent->model && ent->model->DrawDebug != NULL)
3451 ent->model->DrawDebug(ent);
3455 static void R_DrawModelsAddWaterPlanes(void)
3458 entity_render_t *ent;
3460 if (!r_drawentities.integer)
3463 for (i = 0;i < r_refdef.scene.numentities;i++)
3465 if (!r_refdef.viewcache.entityvisible[i])
3467 ent = r_refdef.scene.entities[i];
3468 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3469 ent->model->DrawAddWaterPlanes(ent);
3473 static void R_View_SetFrustum(void)
3476 double slopex, slopey;
3477 vec3_t forward, left, up, origin;
3479 // we can't trust r_refdef.view.forward and friends in reflected scenes
3480 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3483 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3484 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3485 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3486 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3487 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3488 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3489 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3490 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3491 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3492 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3493 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3494 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3498 zNear = r_refdef.nearclip;
3499 nudge = 1.0 - 1.0 / (1<<23);
3500 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3501 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3502 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3503 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3504 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3505 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3506 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3507 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3513 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3514 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3515 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3516 r_refdef.view.frustum[0].dist = m[15] - m[12];
3518 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3519 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3520 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3521 r_refdef.view.frustum[1].dist = m[15] + m[12];
3523 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3524 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3525 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3526 r_refdef.view.frustum[2].dist = m[15] - m[13];
3528 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3529 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3530 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3531 r_refdef.view.frustum[3].dist = m[15] + m[13];
3533 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3534 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3535 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3536 r_refdef.view.frustum[4].dist = m[15] - m[14];
3538 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3539 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3540 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3541 r_refdef.view.frustum[5].dist = m[15] + m[14];
3544 if (r_refdef.view.useperspective)
3546 slopex = 1.0 / r_refdef.view.frustum_x;
3547 slopey = 1.0 / r_refdef.view.frustum_y;
3548 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3549 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3550 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3551 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3552 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3554 // Leaving those out was a mistake, those were in the old code, and they
3555 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3556 // I couldn't reproduce it after adding those normalizations. --blub
3557 VectorNormalize(r_refdef.view.frustum[0].normal);
3558 VectorNormalize(r_refdef.view.frustum[1].normal);
3559 VectorNormalize(r_refdef.view.frustum[2].normal);
3560 VectorNormalize(r_refdef.view.frustum[3].normal);
3562 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3563 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]);
3564 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]);
3565 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]);
3566 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]);
3568 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3569 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3570 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3571 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3572 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3576 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3577 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3578 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3579 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3580 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3581 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3582 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3583 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3584 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3585 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3587 r_refdef.view.numfrustumplanes = 5;
3589 if (r_refdef.view.useclipplane)
3591 r_refdef.view.numfrustumplanes = 6;
3592 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3595 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3596 PlaneClassify(r_refdef.view.frustum + i);
3598 // LordHavoc: note to all quake engine coders, Quake had a special case
3599 // for 90 degrees which assumed a square view (wrong), so I removed it,
3600 // Quake2 has it disabled as well.
3602 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3603 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3604 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3605 //PlaneClassify(&frustum[0]);
3607 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3608 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3609 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3610 //PlaneClassify(&frustum[1]);
3612 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3613 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3614 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3615 //PlaneClassify(&frustum[2]);
3617 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3618 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3619 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3620 //PlaneClassify(&frustum[3]);
3623 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3624 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3625 //PlaneClassify(&frustum[4]);
3628 void R_View_Update(void)
3630 R_View_SetFrustum();
3631 R_View_WorldVisibility(r_refdef.view.useclipplane);
3632 R_View_UpdateEntityVisible();
3633 R_View_UpdateEntityLighting();
3636 void R_SetupView(qboolean allowwaterclippingplane)
3638 const double *customclipplane = NULL;
3640 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3642 // LordHavoc: couldn't figure out how to make this approach the
3643 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3644 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3645 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3646 dist = r_refdef.view.clipplane.dist;
3647 plane[0] = r_refdef.view.clipplane.normal[0];
3648 plane[1] = r_refdef.view.clipplane.normal[1];
3649 plane[2] = r_refdef.view.clipplane.normal[2];
3651 customclipplane = plane;
3654 if (!r_refdef.view.useperspective)
3655 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);
3656 else if (gl_stencil && r_useinfinitefarclip.integer)
3657 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);
3659 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);
3660 R_SetViewport(&r_refdef.view.viewport);
3663 void R_ResetViewRendering2D(void)
3665 r_viewport_t viewport;
3668 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3669 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);
3670 R_SetViewport(&viewport);
3671 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3672 GL_Color(1, 1, 1, 1);
3673 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3674 GL_BlendFunc(GL_ONE, GL_ZERO);
3675 GL_AlphaTest(false);
3676 GL_ScissorTest(false);
3677 GL_DepthMask(false);
3678 GL_DepthRange(0, 1);
3679 GL_DepthTest(false);
3680 R_Mesh_Matrix(&identitymatrix);
3681 R_Mesh_ResetTextureState();
3682 GL_PolygonOffset(0, 0);
3683 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3684 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3685 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3686 qglStencilMask(~0);CHECKGLERROR
3687 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3688 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3689 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3690 R_SetupGenericShader(true);
3693 void R_ResetViewRendering3D(void)
3698 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3699 GL_Color(1, 1, 1, 1);
3700 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3701 GL_BlendFunc(GL_ONE, GL_ZERO);
3702 GL_AlphaTest(false);
3703 GL_ScissorTest(true);
3705 GL_DepthRange(0, 1);
3707 R_Mesh_Matrix(&identitymatrix);
3708 R_Mesh_ResetTextureState();
3709 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3710 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3711 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3712 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3713 qglStencilMask(~0);CHECKGLERROR
3714 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3715 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3716 GL_CullFace(r_refdef.view.cullface_back);
3717 R_SetupGenericShader(true);
3720 void R_RenderScene(void);
3721 void R_RenderWaterPlanes(void);
3723 static void R_Water_StartFrame(void)
3726 int waterwidth, waterheight, texturewidth, textureheight;
3727 r_waterstate_waterplane_t *p;
3729 // set waterwidth and waterheight to the water resolution that will be
3730 // used (often less than the screen resolution for faster rendering)
3731 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3732 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3734 // calculate desired texture sizes
3735 // can't use water if the card does not support the texture size
3736 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3737 texturewidth = textureheight = waterwidth = waterheight = 0;
3738 else if (gl_support_arb_texture_non_power_of_two)
3740 texturewidth = waterwidth;
3741 textureheight = waterheight;
3745 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3746 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3749 // allocate textures as needed
3750 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3752 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3753 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3755 if (p->texture_refraction)
3756 R_FreeTexture(p->texture_refraction);
3757 p->texture_refraction = NULL;
3758 if (p->texture_reflection)
3759 R_FreeTexture(p->texture_reflection);
3760 p->texture_reflection = NULL;
3762 memset(&r_waterstate, 0, sizeof(r_waterstate));
3763 r_waterstate.texturewidth = texturewidth;
3764 r_waterstate.textureheight = textureheight;
3767 if (r_waterstate.texturewidth)
3769 r_waterstate.enabled = true;
3771 // when doing a reduced render (HDR) we want to use a smaller area
3772 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3773 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3775 // set up variables that will be used in shader setup
3776 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3777 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3778 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3779 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3782 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3783 r_waterstate.numwaterplanes = 0;
3786 void R_Water_AddWaterPlane(msurface_t *surface)
3788 int triangleindex, planeindex;
3794 r_waterstate_waterplane_t *p;
3795 texture_t *t = R_GetCurrentTexture(surface->texture);
3796 // just use the first triangle with a valid normal for any decisions
3797 VectorClear(normal);
3798 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3800 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3801 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3802 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3803 TriangleNormal(vert[0], vert[1], vert[2], normal);
3804 if (VectorLength2(normal) >= 0.001)
3808 VectorCopy(normal, plane.normal);
3809 VectorNormalize(plane.normal);
3810 plane.dist = DotProduct(vert[0], plane.normal);
3811 PlaneClassify(&plane);
3812 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3814 // skip backfaces (except if nocullface is set)
3815 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3817 VectorNegate(plane.normal, plane.normal);
3819 PlaneClassify(&plane);
3823 // find a matching plane if there is one
3824 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3825 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3827 if (planeindex >= r_waterstate.maxwaterplanes)
3828 return; // nothing we can do, out of planes
3830 // if this triangle does not fit any known plane rendered this frame, add one
3831 if (planeindex >= r_waterstate.numwaterplanes)
3833 // store the new plane
3834 r_waterstate.numwaterplanes++;
3836 // clear materialflags and pvs
3837 p->materialflags = 0;
3838 p->pvsvalid = false;
3840 // merge this surface's materialflags into the waterplane
3841 p->materialflags |= t->currentmaterialflags;
3842 // merge this surface's PVS into the waterplane
3843 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3844 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3845 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3847 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3852 static void R_Water_ProcessPlanes(void)
3854 r_refdef_view_t originalview;
3855 r_refdef_view_t myview;
3857 r_waterstate_waterplane_t *p;
3859 originalview = r_refdef.view;
3861 // make sure enough textures are allocated
3862 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3864 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3866 if (!p->texture_refraction)
3867 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);
3868 if (!p->texture_refraction)
3872 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3874 if (!p->texture_reflection)
3875 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);
3876 if (!p->texture_reflection)
3882 r_refdef.view = originalview;
3883 r_refdef.view.showdebug = false;
3884 r_refdef.view.width = r_waterstate.waterwidth;
3885 r_refdef.view.height = r_waterstate.waterheight;
3886 r_refdef.view.useclipplane = true;
3887 myview = r_refdef.view;
3888 r_waterstate.renderingscene = true;
3889 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3891 // render the normal view scene and copy into texture
3892 // (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)
3893 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3895 r_refdef.view = myview;
3896 r_refdef.view.clipplane = p->plane;
3897 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3898 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3899 PlaneClassify(&r_refdef.view.clipplane);
3901 R_ResetViewRendering3D();
3902 R_ClearScreen(r_refdef.fogenabled);
3906 // copy view into the screen texture
3907 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3908 GL_ActiveTexture(0);
3910 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
3913 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3915 r_refdef.view = myview;
3916 // render reflected scene and copy into texture
3917 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3918 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3919 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3920 r_refdef.view.clipplane = p->plane;
3921 // reverse the cullface settings for this render
3922 r_refdef.view.cullface_front = GL_FRONT;
3923 r_refdef.view.cullface_back = GL_BACK;
3924 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3926 r_refdef.view.usecustompvs = true;
3928 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3930 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3933 R_ResetViewRendering3D();
3934 R_ClearScreen(r_refdef.fogenabled);
3938 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3939 GL_ActiveTexture(0);
3941 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
3944 r_waterstate.renderingscene = false;
3945 r_refdef.view = originalview;
3946 R_ResetViewRendering3D();
3947 R_ClearScreen(r_refdef.fogenabled);
3951 r_refdef.view = originalview;
3952 r_waterstate.renderingscene = false;
3953 Cvar_SetValueQuick(&r_water, 0);
3954 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3958 void R_Bloom_StartFrame(void)
3960 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3962 // set bloomwidth and bloomheight to the bloom resolution that will be
3963 // used (often less than the screen resolution for faster rendering)
3964 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
3965 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
3966 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
3967 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
3968 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
3970 // calculate desired texture sizes
3971 if (gl_support_arb_texture_non_power_of_two)
3973 screentexturewidth = r_refdef.view.width;
3974 screentextureheight = r_refdef.view.height;
3975 bloomtexturewidth = r_bloomstate.bloomwidth;
3976 bloomtextureheight = r_bloomstate.bloomheight;
3980 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3981 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3982 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3983 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3986 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))
3988 Cvar_SetValueQuick(&r_hdr, 0);
3989 Cvar_SetValueQuick(&r_bloom, 0);
3990 Cvar_SetValueQuick(&r_motionblur, 0);
3991 Cvar_SetValueQuick(&r_damageblur, 0);
3994 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)))
3995 screentexturewidth = screentextureheight = 0;
3996 if (!r_hdr.integer && !r_bloom.integer)
3997 bloomtexturewidth = bloomtextureheight = 0;
3999 // allocate textures as needed
4000 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4002 if (r_bloomstate.texture_screen)
4003 R_FreeTexture(r_bloomstate.texture_screen);
4004 r_bloomstate.texture_screen = NULL;
4005 r_bloomstate.screentexturewidth = screentexturewidth;
4006 r_bloomstate.screentextureheight = screentextureheight;
4007 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4008 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);
4010 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4012 if (r_bloomstate.texture_bloom)
4013 R_FreeTexture(r_bloomstate.texture_bloom);
4014 r_bloomstate.texture_bloom = NULL;
4015 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4016 r_bloomstate.bloomtextureheight = bloomtextureheight;
4017 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4018 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);
4021 // when doing a reduced render (HDR) we want to use a smaller area
4022 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4023 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4024 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4025 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4026 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4028 // set up a texcoord array for the full resolution screen image
4029 // (we have to keep this around to copy back during final render)
4030 r_bloomstate.screentexcoord2f[0] = 0;
4031 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4032 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4033 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4034 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4035 r_bloomstate.screentexcoord2f[5] = 0;
4036 r_bloomstate.screentexcoord2f[6] = 0;
4037 r_bloomstate.screentexcoord2f[7] = 0;
4039 // set up a texcoord array for the reduced resolution bloom image
4040 // (which will be additive blended over the screen image)
4041 r_bloomstate.bloomtexcoord2f[0] = 0;
4042 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4043 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4044 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4045 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4046 r_bloomstate.bloomtexcoord2f[5] = 0;
4047 r_bloomstate.bloomtexcoord2f[6] = 0;
4048 r_bloomstate.bloomtexcoord2f[7] = 0;
4050 if (r_hdr.integer || r_bloom.integer)
4052 r_bloomstate.enabled = true;
4053 r_bloomstate.hdr = r_hdr.integer != 0;
4056 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);
4059 void R_Bloom_CopyBloomTexture(float colorscale)
4061 r_refdef.stats.bloom++;
4063 // scale down screen texture to the bloom texture size
4065 R_SetViewport(&r_bloomstate.viewport);
4066 GL_BlendFunc(GL_ONE, GL_ZERO);
4067 GL_Color(colorscale, colorscale, colorscale, 1);
4068 // TODO: optimize with multitexture or GLSL
4069 R_SetupGenericShader(true);
4070 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4071 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4072 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4073 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4075 // we now have a bloom image in the framebuffer
4076 // copy it into the bloom image texture for later processing
4077 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4078 GL_ActiveTexture(0);
4080 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4081 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4084 void R_Bloom_CopyHDRTexture(void)
4086 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4087 GL_ActiveTexture(0);
4089 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
4090 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4093 void R_Bloom_MakeTexture(void)
4096 float xoffset, yoffset, r, brighten;
4098 r_refdef.stats.bloom++;
4100 R_ResetViewRendering2D();
4101 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4102 R_Mesh_ColorPointer(NULL, 0, 0);
4103 R_SetupGenericShader(true);
4105 // we have a bloom image in the framebuffer
4107 R_SetViewport(&r_bloomstate.viewport);
4109 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4112 r = bound(0, r_bloom_colorexponent.value / x, 1);
4113 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4114 GL_Color(r, r, r, 1);
4115 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4116 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4117 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4118 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4120 // copy the vertically blurred bloom view to a texture
4121 GL_ActiveTexture(0);
4123 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4124 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4127 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4128 brighten = r_bloom_brighten.value;
4130 brighten *= r_hdr_range.value;
4131 brighten = sqrt(brighten);
4133 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4134 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4135 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4137 for (dir = 0;dir < 2;dir++)
4139 // blend on at multiple vertical offsets to achieve a vertical blur
4140 // TODO: do offset blends using GLSL
4141 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4142 GL_BlendFunc(GL_ONE, GL_ZERO);
4143 for (x = -range;x <= range;x++)
4145 if (!dir){xoffset = 0;yoffset = x;}
4146 else {xoffset = x;yoffset = 0;}
4147 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4148 yoffset /= (float)r_bloomstate.bloomtextureheight;
4149 // compute a texcoord array with the specified x and y offset
4150 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4151 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4152 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4153 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4154 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4155 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4156 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4157 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4158 // this r value looks like a 'dot' particle, fading sharply to
4159 // black at the edges
4160 // (probably not realistic but looks good enough)
4161 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4162 //r = brighten/(range*2+1);
4163 r = brighten / (range * 2 + 1);
4165 r *= (1 - x*x/(float)(range*range));
4166 GL_Color(r, r, r, 1);
4167 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4168 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4169 GL_BlendFunc(GL_ONE, GL_ONE);
4172 // copy the vertically blurred bloom view to a texture
4173 GL_ActiveTexture(0);
4175 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4176 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4179 // apply subtract last
4180 // (just like it would be in a GLSL shader)
4181 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4183 GL_BlendFunc(GL_ONE, GL_ZERO);
4184 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4185 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4186 GL_Color(1, 1, 1, 1);
4187 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4188 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4190 GL_BlendFunc(GL_ONE, GL_ONE);
4191 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4192 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4193 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4194 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4195 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4196 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4197 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4199 // copy the darkened bloom view to a texture
4200 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4201 GL_ActiveTexture(0);
4203 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4204 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4208 void R_HDR_RenderBloomTexture(void)
4210 int oldwidth, oldheight;
4211 float oldcolorscale;
4213 oldcolorscale = r_refdef.view.colorscale;
4214 oldwidth = r_refdef.view.width;
4215 oldheight = r_refdef.view.height;
4216 r_refdef.view.width = r_bloomstate.bloomwidth;
4217 r_refdef.view.height = r_bloomstate.bloomheight;
4219 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4220 // TODO: add exposure compensation features
4221 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4223 r_refdef.view.showdebug = false;
4224 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4226 R_ResetViewRendering3D();
4228 R_ClearScreen(r_refdef.fogenabled);
4229 if (r_timereport_active)
4230 R_TimeReport("HDRclear");
4233 if (r_timereport_active)
4234 R_TimeReport("visibility");
4236 // only do secondary renders with HDR if r_hdr is 2 or higher
4237 r_waterstate.numwaterplanes = 0;
4238 if (r_waterstate.enabled && r_hdr.integer >= 2)
4239 R_RenderWaterPlanes();
4241 r_refdef.view.showdebug = true;
4243 r_waterstate.numwaterplanes = 0;
4245 R_ResetViewRendering2D();
4247 R_Bloom_CopyHDRTexture();
4248 R_Bloom_MakeTexture();
4250 // restore the view settings
4251 r_refdef.view.width = oldwidth;
4252 r_refdef.view.height = oldheight;
4253 r_refdef.view.colorscale = oldcolorscale;
4255 R_ResetViewRendering3D();
4257 R_ClearScreen(r_refdef.fogenabled);
4258 if (r_timereport_active)
4259 R_TimeReport("viewclear");
4262 static void R_BlendView(void)
4264 if (r_bloomstate.texture_screen)
4266 // make sure the buffer is available
4267 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4269 R_ResetViewRendering2D();
4270 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4271 R_Mesh_ColorPointer(NULL, 0, 0);
4272 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4273 GL_ActiveTexture(0);CHECKGLERROR
4275 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4277 // declare variables
4279 static float avgspeed;
4281 speed = VectorLength(cl.movement_velocity);
4283 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4284 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4286 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4287 speed = bound(0, speed, 1);
4288 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4290 // calculate values into a standard alpha
4291 cl.motionbluralpha = 1 - exp(-
4293 (r_motionblur.value * speed / 80)
4295 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4298 max(0.0001, cl.time - cl.oldtime) // fps independent
4301 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4302 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4304 if (cl.motionbluralpha > 0)
4306 R_SetupGenericShader(true);
4307 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4308 GL_Color(1, 1, 1, cl.motionbluralpha);
4309 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4310 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4311 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4312 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4316 // copy view into the screen texture
4317 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
4318 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4321 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4323 unsigned int permutation =
4324 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4325 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4326 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4327 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4328 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4330 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4332 // render simple bloom effect
4333 // copy the screen and shrink it and darken it for the bloom process
4334 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4335 // make the bloom texture
4336 R_Bloom_MakeTexture();
4339 R_ResetViewRendering2D();
4340 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4341 R_Mesh_ColorPointer(NULL, 0, 0);
4342 GL_Color(1, 1, 1, 1);
4343 GL_BlendFunc(GL_ONE, GL_ZERO);
4344 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4345 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4346 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4347 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4348 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4349 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4350 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4351 if (r_glsl_permutation->loc_TintColor >= 0)
4352 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4353 if (r_glsl_permutation->loc_ClientTime >= 0)
4354 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4355 if (r_glsl_permutation->loc_PixelSize >= 0)
4356 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4357 if (r_glsl_permutation->loc_UserVec1 >= 0)
4359 float a=0, b=0, c=0, d=0;
4360 #if _MSC_VER >= 1400
4361 #define sscanf sscanf_s
4363 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4364 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4366 if (r_glsl_permutation->loc_UserVec2 >= 0)
4368 float a=0, b=0, c=0, d=0;
4369 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4370 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4372 if (r_glsl_permutation->loc_UserVec3 >= 0)
4374 float a=0, b=0, c=0, d=0;
4375 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4376 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4378 if (r_glsl_permutation->loc_UserVec4 >= 0)
4380 float a=0, b=0, c=0, d=0;
4381 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4382 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4384 if (r_glsl_permutation->loc_Saturation >= 0)
4385 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4386 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4387 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4393 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4395 // render high dynamic range bloom effect
4396 // the bloom texture was made earlier this render, so we just need to
4397 // blend it onto the screen...
4398 R_ResetViewRendering2D();
4399 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4400 R_Mesh_ColorPointer(NULL, 0, 0);
4401 R_SetupGenericShader(true);
4402 GL_Color(1, 1, 1, 1);
4403 GL_BlendFunc(GL_ONE, GL_ONE);
4404 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4405 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4406 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4407 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4409 else if (r_bloomstate.texture_bloom)
4411 // render simple bloom effect
4412 // copy the screen and shrink it and darken it for the bloom process
4413 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4414 // make the bloom texture
4415 R_Bloom_MakeTexture();
4416 // put the original screen image back in place and blend the bloom
4418 R_ResetViewRendering2D();
4419 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4420 R_Mesh_ColorPointer(NULL, 0, 0);
4421 GL_Color(1, 1, 1, 1);
4422 GL_BlendFunc(GL_ONE, GL_ZERO);
4423 // do both in one pass if possible
4424 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4425 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4426 if (r_textureunits.integer >= 2 && gl_combine.integer)
4428 R_SetupGenericTwoTextureShader(GL_ADD);
4429 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4430 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4434 R_SetupGenericShader(true);
4435 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4436 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4437 // now blend on the bloom texture
4438 GL_BlendFunc(GL_ONE, GL_ONE);
4439 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4440 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4442 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4443 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4445 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4447 // apply a color tint to the whole view
4448 R_ResetViewRendering2D();
4449 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4450 R_Mesh_ColorPointer(NULL, 0, 0);
4451 R_SetupGenericShader(false);
4452 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4453 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4454 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4458 matrix4x4_t r_waterscrollmatrix;
4460 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4462 if (r_refdef.fog_density)
4464 r_refdef.fogcolor[0] = r_refdef.fog_red;
4465 r_refdef.fogcolor[1] = r_refdef.fog_green;
4466 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4470 VectorCopy(r_refdef.fogcolor, fogvec);
4471 // color.rgb *= ContrastBoost * SceneBrightness;
4472 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4473 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4474 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4475 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4480 void R_UpdateVariables(void)
4484 r_refdef.scene.ambient = r_ambient.value;
4486 r_refdef.farclip = 4096;
4487 if (r_refdef.scene.worldmodel)
4488 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4489 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4491 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4492 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4493 r_refdef.polygonfactor = 0;
4494 r_refdef.polygonoffset = 0;
4495 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4496 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4498 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4499 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4500 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4501 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4502 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4503 if (r_showsurfaces.integer)
4505 r_refdef.scene.rtworld = false;
4506 r_refdef.scene.rtworldshadows = false;
4507 r_refdef.scene.rtdlight = false;
4508 r_refdef.scene.rtdlightshadows = false;
4509 r_refdef.lightmapintensity = 0;
4512 if (gamemode == GAME_NEHAHRA)
4514 if (gl_fogenable.integer)
4516 r_refdef.oldgl_fogenable = true;
4517 r_refdef.fog_density = gl_fogdensity.value;
4518 r_refdef.fog_red = gl_fogred.value;
4519 r_refdef.fog_green = gl_foggreen.value;
4520 r_refdef.fog_blue = gl_fogblue.value;
4521 r_refdef.fog_alpha = 1;
4522 r_refdef.fog_start = 0;
4523 r_refdef.fog_end = gl_skyclip.value;
4525 else if (r_refdef.oldgl_fogenable)
4527 r_refdef.oldgl_fogenable = false;
4528 r_refdef.fog_density = 0;
4529 r_refdef.fog_red = 0;
4530 r_refdef.fog_green = 0;
4531 r_refdef.fog_blue = 0;
4532 r_refdef.fog_alpha = 0;
4533 r_refdef.fog_start = 0;
4534 r_refdef.fog_end = 0;
4538 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4539 r_refdef.fog_start = max(0, r_refdef.fog_start);
4540 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4542 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4544 if (r_refdef.fog_density && r_drawfog.integer)
4546 r_refdef.fogenabled = true;
4547 // this is the point where the fog reaches 0.9986 alpha, which we
4548 // consider a good enough cutoff point for the texture
4549 // (0.9986 * 256 == 255.6)
4550 if (r_fog_exp2.integer)
4551 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4553 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4554 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4555 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4556 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4557 // fog color was already set
4558 // update the fog texture
4559 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)
4560 R_BuildFogTexture();
4563 r_refdef.fogenabled = false;
4565 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4567 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4569 // build GLSL gamma texture
4570 #define RAMPWIDTH 256
4571 unsigned short ramp[RAMPWIDTH * 3];
4572 unsigned char rampbgr[RAMPWIDTH][4];
4575 r_texture_gammaramps_serial = vid_gammatables_serial;
4577 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4578 for(i = 0; i < RAMPWIDTH; ++i)
4580 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4581 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4582 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4585 if (r_texture_gammaramps)
4587 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4591 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);
4597 // remove GLSL gamma texture
4601 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4602 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4608 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4609 if( scenetype != r_currentscenetype ) {
4610 // store the old scenetype
4611 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4612 r_currentscenetype = scenetype;
4613 // move in the new scene
4614 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4623 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4625 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4626 if( scenetype == r_currentscenetype ) {
4627 return &r_refdef.scene;
4629 return &r_scenes_store[ scenetype ];
4638 void R_RenderView(void)
4640 if (r_timereport_active)
4641 R_TimeReport("start");
4642 r_frame++; // used only by R_GetCurrentTexture
4643 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4645 R_AnimCache_NewFrame();
4647 if (r_refdef.view.isoverlay)
4649 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4650 GL_Clear( GL_DEPTH_BUFFER_BIT );
4651 R_TimeReport("depthclear");
4653 r_refdef.view.showdebug = false;
4655 r_waterstate.enabled = false;
4656 r_waterstate.numwaterplanes = 0;
4664 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4665 return; //Host_Error ("R_RenderView: NULL worldmodel");
4667 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4669 // break apart the view matrix into vectors for various purposes
4670 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4671 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4672 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4673 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4674 // make an inverted copy of the view matrix for tracking sprites
4675 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4677 R_Shadow_UpdateWorldLightSelection();
4679 R_Bloom_StartFrame();
4680 R_Water_StartFrame();
4683 if (r_timereport_active)
4684 R_TimeReport("viewsetup");
4686 R_ResetViewRendering3D();
4688 if (r_refdef.view.clear || r_refdef.fogenabled)
4690 R_ClearScreen(r_refdef.fogenabled);
4691 if (r_timereport_active)
4692 R_TimeReport("viewclear");
4694 r_refdef.view.clear = true;
4696 // this produces a bloom texture to be used in R_BlendView() later
4698 R_HDR_RenderBloomTexture();
4700 r_refdef.view.showdebug = true;
4703 if (r_timereport_active)
4704 R_TimeReport("visibility");
4706 r_waterstate.numwaterplanes = 0;
4707 if (r_waterstate.enabled)
4708 R_RenderWaterPlanes();
4711 r_waterstate.numwaterplanes = 0;
4714 if (r_timereport_active)
4715 R_TimeReport("blendview");
4717 GL_Scissor(0, 0, vid.width, vid.height);
4718 GL_ScissorTest(false);
4722 void R_RenderWaterPlanes(void)
4724 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4726 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4727 if (r_timereport_active)
4728 R_TimeReport("waterworld");
4731 // don't let sound skip if going slow
4732 if (r_refdef.scene.extraupdate)
4735 R_DrawModelsAddWaterPlanes();
4736 if (r_timereport_active)
4737 R_TimeReport("watermodels");
4739 if (r_waterstate.numwaterplanes)
4741 R_Water_ProcessPlanes();
4742 if (r_timereport_active)
4743 R_TimeReport("waterscenes");
4747 extern void R_DrawLightningBeams (void);
4748 extern void VM_CL_AddPolygonsToMeshQueue (void);
4749 extern void R_DrawPortals (void);
4750 extern cvar_t cl_locs_show;
4751 static void R_DrawLocs(void);
4752 static void R_DrawEntityBBoxes(void);
4753 void R_RenderScene(void)
4755 r_refdef.stats.renders++;
4759 // don't let sound skip if going slow
4760 if (r_refdef.scene.extraupdate)
4763 R_MeshQueue_BeginScene();
4767 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);
4769 if (cl.csqc_vidvars.drawworld)
4771 // don't let sound skip if going slow
4772 if (r_refdef.scene.extraupdate)
4775 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4777 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4778 if (r_timereport_active)
4779 R_TimeReport("worldsky");
4782 if (R_DrawBrushModelsSky() && r_timereport_active)
4783 R_TimeReport("bmodelsky");
4786 R_AnimCache_CacheVisibleEntities();
4788 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4790 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4791 if (r_timereport_active)
4792 R_TimeReport("worlddepth");
4794 if (r_depthfirst.integer >= 2)
4796 R_DrawModelsDepth();
4797 if (r_timereport_active)
4798 R_TimeReport("modeldepth");
4801 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4803 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4804 if (r_timereport_active)
4805 R_TimeReport("world");
4808 // don't let sound skip if going slow
4809 if (r_refdef.scene.extraupdate)
4813 if (r_timereport_active)
4814 R_TimeReport("models");
4816 // don't let sound skip if going slow
4817 if (r_refdef.scene.extraupdate)
4820 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4822 R_DrawModelShadows();
4823 R_ResetViewRendering3D();
4824 // don't let sound skip if going slow
4825 if (r_refdef.scene.extraupdate)
4829 R_ShadowVolumeLighting(false);
4830 if (r_timereport_active)
4831 R_TimeReport("rtlights");
4833 // don't let sound skip if going slow
4834 if (r_refdef.scene.extraupdate)
4837 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4839 R_DrawModelShadows();
4840 R_ResetViewRendering3D();
4841 // don't let sound skip if going slow
4842 if (r_refdef.scene.extraupdate)
4846 if (cl.csqc_vidvars.drawworld)
4848 R_DrawLightningBeams();
4849 if (r_timereport_active)
4850 R_TimeReport("lightning");
4853 if (r_timereport_active)
4854 R_TimeReport("decals");
4857 if (r_timereport_active)
4858 R_TimeReport("particles");
4861 if (r_timereport_active)
4862 R_TimeReport("explosions");
4865 R_SetupGenericShader(true);
4866 VM_CL_AddPolygonsToMeshQueue();
4868 if (r_refdef.view.showdebug)
4870 if (cl_locs_show.integer)
4873 if (r_timereport_active)
4874 R_TimeReport("showlocs");
4877 if (r_drawportals.integer)
4880 if (r_timereport_active)
4881 R_TimeReport("portals");
4884 if (r_showbboxes.value > 0)
4886 R_DrawEntityBBoxes();
4887 if (r_timereport_active)
4888 R_TimeReport("bboxes");
4892 R_SetupGenericShader(true);
4893 R_MeshQueue_RenderTransparent();
4894 if (r_timereport_active)
4895 R_TimeReport("drawtrans");
4897 R_SetupGenericShader(true);
4899 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))
4901 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4902 if (r_timereport_active)
4903 R_TimeReport("worlddebug");
4904 R_DrawModelsDebug();
4905 if (r_timereport_active)
4906 R_TimeReport("modeldebug");
4909 R_SetupGenericShader(true);
4911 if (cl.csqc_vidvars.drawworld)
4914 if (r_timereport_active)
4915 R_TimeReport("coronas");
4918 // don't let sound skip if going slow
4919 if (r_refdef.scene.extraupdate)
4922 R_ResetViewRendering2D();
4925 static const unsigned short bboxelements[36] =
4935 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4938 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4939 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4940 GL_DepthMask(false);
4941 GL_DepthRange(0, 1);
4942 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4943 R_Mesh_Matrix(&identitymatrix);
4944 R_Mesh_ResetTextureState();
4946 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
4947 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
4949 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4950 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4951 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4952 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4953 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4954 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4955 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4956 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4957 R_FillColors(color4f, 8, cr, cg, cb, ca);
4958 if (r_refdef.fogenabled)
4960 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4962 f1 = RSurf_FogVertex(v);
4964 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4965 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4966 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4969 R_Mesh_VertexPointer(vertex3f, 0, 0);
4970 R_Mesh_ColorPointer(color4f, 0, 0);
4971 R_Mesh_ResetTextureState();
4972 R_SetupGenericShader(false);
4973 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4976 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4980 prvm_edict_t *edict;
4981 prvm_prog_t *prog_save = prog;
4983 // this function draws bounding boxes of server entities
4987 GL_CullFace(GL_NONE);
4988 R_SetupGenericShader(false);
4992 for (i = 0;i < numsurfaces;i++)
4994 edict = PRVM_EDICT_NUM(surfacelist[i]);
4995 switch ((int)edict->fields.server->solid)
4997 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4998 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4999 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5000 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5001 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5002 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5004 color[3] *= r_showbboxes.value;
5005 color[3] = bound(0, color[3], 1);
5006 GL_DepthTest(!r_showdisabledepthtest.integer);
5007 GL_CullFace(r_refdef.view.cullface_front);
5008 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5014 static void R_DrawEntityBBoxes(void)
5017 prvm_edict_t *edict;
5019 prvm_prog_t *prog_save = prog;
5021 // this function draws bounding boxes of server entities
5027 for (i = 0;i < prog->num_edicts;i++)
5029 edict = PRVM_EDICT_NUM(i);
5030 if (edict->priv.server->free)
5032 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5033 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5035 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5037 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5038 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5044 unsigned short nomodelelements[24] =
5056 float nomodelvertex3f[6*3] =
5066 float nomodelcolor4f[6*4] =
5068 0.0f, 0.0f, 0.5f, 1.0f,
5069 0.0f, 0.0f, 0.5f, 1.0f,
5070 0.0f, 0.5f, 0.0f, 1.0f,
5071 0.0f, 0.5f, 0.0f, 1.0f,
5072 0.5f, 0.0f, 0.0f, 1.0f,
5073 0.5f, 0.0f, 0.0f, 1.0f
5076 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5082 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5083 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5085 // this is only called once per entity so numsurfaces is always 1, and
5086 // surfacelist is always {0}, so this code does not handle batches
5087 R_Mesh_Matrix(&ent->matrix);
5089 if (ent->flags & EF_ADDITIVE)
5091 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5092 GL_DepthMask(false);
5094 else if (ent->alpha < 1)
5096 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5097 GL_DepthMask(false);
5101 GL_BlendFunc(GL_ONE, GL_ZERO);
5104 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5105 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5106 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
5107 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5108 R_SetupGenericShader(false);
5109 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
5110 if (r_refdef.fogenabled)
5113 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5114 R_Mesh_ColorPointer(color4f, 0, 0);
5115 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5116 f1 = RSurf_FogVertex(org);
5118 for (i = 0, c = color4f;i < 6;i++, c += 4)
5120 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5121 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5122 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5126 else if (ent->alpha != 1)
5128 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5129 R_Mesh_ColorPointer(color4f, 0, 0);
5130 for (i = 0, c = color4f;i < 6;i++, c += 4)
5134 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
5135 R_Mesh_ResetTextureState();
5136 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
5139 void R_DrawNoModel(entity_render_t *ent)
5142 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5143 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
5144 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5146 // R_DrawNoModelCallback(ent, 0);
5149 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5151 vec3_t right1, right2, diff, normal;
5153 VectorSubtract (org2, org1, normal);
5155 // calculate 'right' vector for start
5156 VectorSubtract (r_refdef.view.origin, org1, diff);
5157 CrossProduct (normal, diff, right1);
5158 VectorNormalize (right1);
5160 // calculate 'right' vector for end
5161 VectorSubtract (r_refdef.view.origin, org2, diff);
5162 CrossProduct (normal, diff, right2);
5163 VectorNormalize (right2);
5165 vert[ 0] = org1[0] + width * right1[0];
5166 vert[ 1] = org1[1] + width * right1[1];
5167 vert[ 2] = org1[2] + width * right1[2];
5168 vert[ 3] = org1[0] - width * right1[0];
5169 vert[ 4] = org1[1] - width * right1[1];
5170 vert[ 5] = org1[2] - width * right1[2];
5171 vert[ 6] = org2[0] - width * right2[0];
5172 vert[ 7] = org2[1] - width * right2[1];
5173 vert[ 8] = org2[2] - width * right2[2];
5174 vert[ 9] = org2[0] + width * right2[0];
5175 vert[10] = org2[1] + width * right2[1];
5176 vert[11] = org2[2] + width * right2[2];
5179 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5181 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
5183 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
5187 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5188 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5190 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
5191 fog = RSurf_FogVertex(origin);
5193 R_Mesh_Matrix(&identitymatrix);
5194 GL_BlendFunc(blendfunc1, blendfunc2);
5196 GL_CullFace(GL_NONE);
5198 GL_DepthMask(false);
5199 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5200 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5201 GL_DepthTest(!depthdisable);
5203 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5204 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5205 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5206 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5207 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5208 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5209 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5210 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5211 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5212 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5213 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5214 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5216 R_Mesh_VertexPointer(vertex3f, 0, 0);
5217 R_Mesh_ColorPointer(NULL, 0, 0);
5218 R_Mesh_ResetTextureState();
5219 R_SetupGenericShader(true);
5220 R_Mesh_TexBind(0, R_GetTexture(texture));
5221 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5222 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5223 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5224 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5226 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5228 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5229 GL_BlendFunc(blendfunc1, GL_ONE);
5231 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5232 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5236 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5241 VectorSet(v, x, y, z);
5242 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5243 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5245 if (i == mesh->numvertices)
5247 if (mesh->numvertices < mesh->maxvertices)
5249 VectorCopy(v, vertex3f);
5250 mesh->numvertices++;
5252 return mesh->numvertices;
5258 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5262 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5263 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5264 e = mesh->element3i + mesh->numtriangles * 3;
5265 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5267 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5268 if (mesh->numtriangles < mesh->maxtriangles)
5273 mesh->numtriangles++;
5275 element[1] = element[2];
5279 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5283 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5284 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5285 e = mesh->element3i + mesh->numtriangles * 3;
5286 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5288 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5289 if (mesh->numtriangles < mesh->maxtriangles)
5294 mesh->numtriangles++;
5296 element[1] = element[2];
5300 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5301 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5303 int planenum, planenum2;
5306 mplane_t *plane, *plane2;
5308 double temppoints[2][256*3];
5309 // figure out how large a bounding box we need to properly compute this brush
5311 for (w = 0;w < numplanes;w++)
5312 maxdist = max(maxdist, fabs(planes[w].dist));
5313 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5314 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5315 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5319 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5320 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5322 if (planenum2 == planenum)
5324 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);
5327 if (tempnumpoints < 3)
5329 // generate elements forming a triangle fan for this polygon
5330 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5334 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)
5336 texturelayer_t *layer;
5337 layer = t->currentlayers + t->currentnumlayers++;
5339 layer->depthmask = depthmask;
5340 layer->blendfunc1 = blendfunc1;
5341 layer->blendfunc2 = blendfunc2;
5342 layer->texture = texture;
5343 layer->texmatrix = *matrix;
5344 layer->color[0] = r * r_refdef.view.colorscale;
5345 layer->color[1] = g * r_refdef.view.colorscale;
5346 layer->color[2] = b * r_refdef.view.colorscale;
5347 layer->color[3] = a;
5350 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5353 index = parms[2] + r_refdef.scene.time * parms[3];
5354 index -= floor(index);
5358 case Q3WAVEFUNC_NONE:
5359 case Q3WAVEFUNC_NOISE:
5360 case Q3WAVEFUNC_COUNT:
5363 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5364 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5365 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5366 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5367 case Q3WAVEFUNC_TRIANGLE:
5369 f = index - floor(index);
5380 return (float)(parms[0] + parms[1] * f);
5383 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5388 matrix4x4_t matrix, temp;
5389 switch(tcmod->tcmod)
5393 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5394 matrix = r_waterscrollmatrix;
5396 matrix = identitymatrix;
5398 case Q3TCMOD_ENTITYTRANSLATE:
5399 // this is used in Q3 to allow the gamecode to control texcoord
5400 // scrolling on the entity, which is not supported in darkplaces yet.
5401 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5403 case Q3TCMOD_ROTATE:
5404 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5405 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5406 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5409 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5411 case Q3TCMOD_SCROLL:
5412 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5414 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5415 w = (int) tcmod->parms[0];
5416 h = (int) tcmod->parms[1];
5417 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5419 idx = (int) floor(f * w * h);
5420 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5422 case Q3TCMOD_STRETCH:
5423 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5424 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5426 case Q3TCMOD_TRANSFORM:
5427 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5428 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5429 VectorSet(tcmat + 6, 0 , 0 , 1);
5430 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5431 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5433 case Q3TCMOD_TURBULENT:
5434 // this is handled in the RSurf_PrepareVertices function
5435 matrix = identitymatrix;
5439 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5442 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5444 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5445 char name[MAX_QPATH];
5446 skinframe_t *skinframe;
5447 unsigned char pixels[296*194];
5448 strlcpy(cache->name, skinname, sizeof(cache->name));
5449 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5450 if (developer_loading.integer)
5451 Con_Printf("loading %s\n", name);
5452 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5453 if (!skinframe || !skinframe->base)
5456 fs_offset_t filesize;
5458 f = FS_LoadFile(name, tempmempool, true, &filesize);
5461 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5462 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5466 cache->skinframe = skinframe;
5469 texture_t *R_GetCurrentTexture(texture_t *t)
5472 const entity_render_t *ent = rsurface.entity;
5473 dp_model_t *model = ent->model;
5474 q3shaderinfo_layer_tcmod_t *tcmod;
5476 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5477 return t->currentframe;
5478 t->update_lastrenderframe = r_frame;
5479 t->update_lastrenderentity = (void *)ent;
5481 // switch to an alternate material if this is a q1bsp animated material
5483 texture_t *texture = t;
5484 int s = ent->skinnum;
5485 if ((unsigned int)s >= (unsigned int)model->numskins)
5487 if (model->skinscenes)
5489 if (model->skinscenes[s].framecount > 1)
5490 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5492 s = model->skinscenes[s].firstframe;
5495 t = t + s * model->num_surfaces;
5498 // use an alternate animation if the entity's frame is not 0,
5499 // and only if the texture has an alternate animation
5500 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
5501 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5503 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5505 texture->currentframe = t;
5508 // update currentskinframe to be a qw skin or animation frame
5509 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[i].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl"))
5511 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5513 r_qwskincache_size = cl.maxclients;
5515 Mem_Free(r_qwskincache);
5516 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5518 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5519 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5520 t->currentskinframe = r_qwskincache[i].skinframe;
5521 if (t->currentskinframe == NULL)
5522 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5524 else if (t->numskinframes >= 2)
5525 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5526 if (t->backgroundnumskinframes >= 2)
5527 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
5529 t->currentmaterialflags = t->basematerialflags;
5530 t->currentalpha = ent->alpha;
5531 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5532 t->currentalpha *= r_wateralpha.value;
5533 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5534 t->currentalpha *= t->r_water_wateralpha;
5535 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5536 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5537 if (!(ent->flags & RENDER_LIGHT))
5538 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5539 else if (rsurface.modeltexcoordlightmap2f == NULL)
5541 // pick a model lighting mode
5542 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5543 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5545 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5547 if (ent->effects & EF_ADDITIVE)
5548 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5549 else if (t->currentalpha < 1)
5550 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5551 if (ent->effects & EF_DOUBLESIDED)
5552 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5553 if (ent->effects & EF_NODEPTHTEST)
5554 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5555 if (ent->flags & RENDER_VIEWMODEL)
5556 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5557 if (t->backgroundnumskinframes)
5558 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5559 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5561 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5562 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5565 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5567 // there is no tcmod
5568 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5570 t->currenttexmatrix = r_waterscrollmatrix;
5571 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5575 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5576 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5579 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5580 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5581 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5582 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5584 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5585 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5586 t->glosstexture = r_texture_black;
5587 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5588 t->backgroundglosstexture = r_texture_black;
5589 t->specularpower = r_shadow_glossexponent.value;
5590 // TODO: store reference values for these in the texture?
5591 t->specularscale = 0;
5592 if (r_shadow_gloss.integer > 0)
5594 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5596 if (r_shadow_glossintensity.value > 0)
5598 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5599 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5600 t->specularscale = r_shadow_glossintensity.value;
5603 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5605 t->glosstexture = r_texture_white;
5606 t->backgroundglosstexture = r_texture_white;
5607 t->specularscale = r_shadow_gloss2intensity.value;
5608 t->specularpower = r_shadow_gloss2exponent.value;
5611 t->specularscale *= t->specularscalemod;
5612 t->specularpower *= t->specularpowermod;
5614 // lightmaps mode looks bad with dlights using actual texturing, so turn
5615 // off the colormap and glossmap, but leave the normalmap on as it still
5616 // accurately represents the shading involved
5617 if (gl_lightmaps.integer)
5619 t->basetexture = r_texture_grey128;
5620 t->backgroundbasetexture = NULL;
5621 t->specularscale = 0;
5622 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5625 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5626 VectorClear(t->dlightcolor);
5627 t->currentnumlayers = 0;
5628 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5631 int blendfunc1, blendfunc2;
5633 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5635 blendfunc1 = GL_SRC_ALPHA;
5636 blendfunc2 = GL_ONE;
5638 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5640 blendfunc1 = GL_SRC_ALPHA;
5641 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5643 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5645 blendfunc1 = t->customblendfunc[0];
5646 blendfunc2 = t->customblendfunc[1];
5650 blendfunc1 = GL_ONE;
5651 blendfunc2 = GL_ZERO;
5653 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5654 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5655 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5656 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5658 // fullbright is not affected by r_refdef.lightmapintensity
5659 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]);
5660 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5661 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5662 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5663 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5667 vec3_t ambientcolor;
5669 // set the color tint used for lights affecting this surface
5670 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5672 // q3bsp has no lightmap updates, so the lightstylevalue that
5673 // would normally be baked into the lightmap must be
5674 // applied to the color
5675 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5676 if (ent->model->type == mod_brushq3)
5677 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5678 colorscale *= r_refdef.lightmapintensity;
5679 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5680 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5681 // basic lit geometry
5682 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]);
5683 // add pants/shirt if needed
5684 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5685 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5686 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5687 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5688 // now add ambient passes if needed
5689 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5691 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]);
5692 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5693 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
5694 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5695 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
5698 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5699 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]);
5700 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5702 // if this is opaque use alpha blend which will darken the earlier
5705 // if this is an alpha blended material, all the earlier passes
5706 // were darkened by fog already, so we only need to add the fog
5707 // color ontop through the fog mask texture
5709 // if this is an additive blended material, all the earlier passes
5710 // were darkened by fog already, and we should not add fog color
5711 // (because the background was not darkened, there is no fog color
5712 // that was lost behind it).
5713 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]);
5717 return t->currentframe;
5720 rsurfacestate_t rsurface;
5722 void R_Mesh_ResizeArrays(int newvertices)
5725 if (rsurface.array_size >= newvertices)
5727 if (rsurface.array_modelvertex3f)
5728 Mem_Free(rsurface.array_modelvertex3f);
5729 rsurface.array_size = (newvertices + 1023) & ~1023;
5730 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5731 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5732 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5733 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5734 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5735 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5736 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5737 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5738 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5739 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5740 rsurface.array_color4f = base + rsurface.array_size * 27;
5741 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5744 void RSurf_ActiveWorldEntity(void)
5746 dp_model_t *model = r_refdef.scene.worldmodel;
5747 //if (rsurface.entity == r_refdef.scene.worldentity)
5749 rsurface.entity = r_refdef.scene.worldentity;
5750 if (rsurface.array_size < model->surfmesh.num_vertices)
5751 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5752 rsurface.matrix = identitymatrix;
5753 rsurface.inversematrix = identitymatrix;
5754 R_Mesh_Matrix(&identitymatrix);
5755 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5756 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5757 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5758 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5759 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5760 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5761 VectorSet(rsurface.glowmod, 1, 1, 1);
5762 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5763 rsurface.frameblend[0].lerp = 1;
5764 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5765 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5766 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5767 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5768 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5769 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5770 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5771 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5772 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5773 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5774 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5775 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5776 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5777 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5778 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5779 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5780 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5781 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5782 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5783 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5784 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5785 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5786 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5787 rsurface.modelelement3i = model->surfmesh.data_element3i;
5788 rsurface.modelelement3s = model->surfmesh.data_element3s;
5789 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5790 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5791 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5792 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5793 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5794 rsurface.modelsurfaces = model->data_surfaces;
5795 rsurface.generatedvertex = false;
5796 rsurface.vertex3f = rsurface.modelvertex3f;
5797 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5798 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5799 rsurface.svector3f = rsurface.modelsvector3f;
5800 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5801 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5802 rsurface.tvector3f = rsurface.modeltvector3f;
5803 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5804 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5805 rsurface.normal3f = rsurface.modelnormal3f;
5806 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5807 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5808 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5811 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5813 dp_model_t *model = ent->model;
5814 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5816 rsurface.entity = (entity_render_t *)ent;
5817 if (rsurface.array_size < model->surfmesh.num_vertices)
5818 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5819 rsurface.matrix = ent->matrix;
5820 rsurface.inversematrix = ent->inversematrix;
5821 R_Mesh_Matrix(&rsurface.matrix);
5822 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
5823 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5824 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5825 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5826 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5827 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5828 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5829 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5830 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5831 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5832 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5833 VectorCopy(ent->glowmod, rsurface.glowmod);
5834 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5835 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5836 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5837 if (ent->model->brush.submodel)
5839 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5840 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5842 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5844 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5846 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5847 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5848 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5849 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5851 else if (wanttangents)
5853 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5854 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5855 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5856 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5857 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5859 else if (wantnormals)
5861 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5862 rsurface.modelsvector3f = NULL;
5863 rsurface.modeltvector3f = NULL;
5864 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5865 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5869 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5870 rsurface.modelsvector3f = NULL;
5871 rsurface.modeltvector3f = NULL;
5872 rsurface.modelnormal3f = NULL;
5873 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5875 rsurface.modelvertex3f_bufferobject = 0;
5876 rsurface.modelvertex3f_bufferoffset = 0;
5877 rsurface.modelsvector3f_bufferobject = 0;
5878 rsurface.modelsvector3f_bufferoffset = 0;
5879 rsurface.modeltvector3f_bufferobject = 0;
5880 rsurface.modeltvector3f_bufferoffset = 0;
5881 rsurface.modelnormal3f_bufferobject = 0;
5882 rsurface.modelnormal3f_bufferoffset = 0;
5883 rsurface.generatedvertex = true;
5887 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5888 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5889 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5890 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5891 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5892 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5893 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5894 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5895 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5896 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5897 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5898 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5899 rsurface.generatedvertex = false;
5901 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5902 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5903 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5904 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5905 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5906 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5907 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5908 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5909 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5910 rsurface.modelelement3i = model->surfmesh.data_element3i;
5911 rsurface.modelelement3s = model->surfmesh.data_element3s;
5912 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5913 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5914 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5915 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5916 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5917 rsurface.modelsurfaces = model->data_surfaces;
5918 rsurface.vertex3f = rsurface.modelvertex3f;
5919 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5920 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5921 rsurface.svector3f = rsurface.modelsvector3f;
5922 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5923 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5924 rsurface.tvector3f = rsurface.modeltvector3f;
5925 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5926 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5927 rsurface.normal3f = rsurface.modelnormal3f;
5928 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5929 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5930 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5933 float RSurf_FogVertex(const float *v)
5935 float len = VectorDistance(rsurface.localvieworigin, v);
5936 unsigned int fogmasktableindex;
5937 fogmasktableindex = (unsigned int)(len * r_refdef.fogmasktabledistmultiplier);
5938 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
5941 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5942 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5945 int texturesurfaceindex;
5950 const float *v1, *in_tc;
5952 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5954 q3shaderinfo_deform_t *deform;
5955 // 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
5956 if (rsurface.generatedvertex)
5958 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5959 generatenormals = true;
5960 for (i = 0;i < Q3MAXDEFORMS;i++)
5962 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5964 generatetangents = true;
5965 generatenormals = true;
5967 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5968 generatenormals = true;
5970 if (generatenormals && !rsurface.modelnormal3f)
5972 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5973 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5974 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5975 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
5977 if (generatetangents && !rsurface.modelsvector3f)
5979 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5980 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5981 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5982 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5983 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5984 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5985 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);
5988 rsurface.vertex3f = rsurface.modelvertex3f;
5989 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5990 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5991 rsurface.svector3f = rsurface.modelsvector3f;
5992 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5993 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5994 rsurface.tvector3f = rsurface.modeltvector3f;
5995 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5996 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5997 rsurface.normal3f = rsurface.modelnormal3f;
5998 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5999 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6000 // if vertices are deformed (sprite flares and things in maps, possibly
6001 // water waves, bulges and other deformations), generate them into
6002 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6003 // (may be static model data or generated data for an animated model, or
6004 // the previous deform pass)
6005 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6007 switch (deform->deform)
6010 case Q3DEFORM_PROJECTIONSHADOW:
6011 case Q3DEFORM_TEXT0:
6012 case Q3DEFORM_TEXT1:
6013 case Q3DEFORM_TEXT2:
6014 case Q3DEFORM_TEXT3:
6015 case Q3DEFORM_TEXT4:
6016 case Q3DEFORM_TEXT5:
6017 case Q3DEFORM_TEXT6:
6018 case Q3DEFORM_TEXT7:
6021 case Q3DEFORM_AUTOSPRITE:
6022 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6023 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6024 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6025 VectorNormalize(newforward);
6026 VectorNormalize(newright);
6027 VectorNormalize(newup);
6028 // make deformed versions of only the model vertices used by the specified surfaces
6029 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6031 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6032 // a single autosprite surface can contain multiple sprites...
6033 for (j = 0;j < surface->num_vertices - 3;j += 4)
6035 VectorClear(center);
6036 for (i = 0;i < 4;i++)
6037 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6038 VectorScale(center, 0.25f, center);
6039 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6040 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6041 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6042 for (i = 0;i < 4;i++)
6044 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6045 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6048 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);
6049 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);
6051 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6052 rsurface.vertex3f_bufferobject = 0;
6053 rsurface.vertex3f_bufferoffset = 0;
6054 rsurface.svector3f = rsurface.array_deformedsvector3f;
6055 rsurface.svector3f_bufferobject = 0;
6056 rsurface.svector3f_bufferoffset = 0;
6057 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6058 rsurface.tvector3f_bufferobject = 0;
6059 rsurface.tvector3f_bufferoffset = 0;
6060 rsurface.normal3f = rsurface.array_deformednormal3f;
6061 rsurface.normal3f_bufferobject = 0;
6062 rsurface.normal3f_bufferoffset = 0;
6064 case Q3DEFORM_AUTOSPRITE2:
6065 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6066 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6067 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6068 VectorNormalize(newforward);
6069 VectorNormalize(newright);
6070 VectorNormalize(newup);
6071 // make deformed versions of only the model vertices used by the specified surfaces
6072 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6074 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6075 const float *v1, *v2;
6085 memset(shortest, 0, sizeof(shortest));
6086 // a single autosprite surface can contain multiple sprites...
6087 for (j = 0;j < surface->num_vertices - 3;j += 4)
6089 VectorClear(center);
6090 for (i = 0;i < 4;i++)
6091 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6092 VectorScale(center, 0.25f, center);
6093 // find the two shortest edges, then use them to define the
6094 // axis vectors for rotating around the central axis
6095 for (i = 0;i < 6;i++)
6097 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6098 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6100 Debug_PolygonBegin(NULL, 0);
6101 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6102 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);
6103 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6106 l = VectorDistance2(v1, v2);
6107 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6109 l += (1.0f / 1024.0f);
6110 if (shortest[0].length2 > l || i == 0)
6112 shortest[1] = shortest[0];
6113 shortest[0].length2 = l;
6114 shortest[0].v1 = v1;
6115 shortest[0].v2 = v2;
6117 else if (shortest[1].length2 > l || i == 1)
6119 shortest[1].length2 = l;
6120 shortest[1].v1 = v1;
6121 shortest[1].v2 = v2;
6124 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6125 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6127 Debug_PolygonBegin(NULL, 0);
6128 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6129 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);
6130 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6133 // this calculates the right vector from the shortest edge
6134 // and the up vector from the edge midpoints
6135 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6136 VectorNormalize(right);
6137 VectorSubtract(end, start, up);
6138 VectorNormalize(up);
6139 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6140 VectorSubtract(rsurface.localvieworigin, center, forward);
6141 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6142 VectorNegate(forward, forward);
6143 VectorReflect(forward, 0, up, forward);
6144 VectorNormalize(forward);
6145 CrossProduct(up, forward, newright);
6146 VectorNormalize(newright);
6148 Debug_PolygonBegin(NULL, 0);
6149 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);
6150 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6151 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6155 Debug_PolygonBegin(NULL, 0);
6156 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6157 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6158 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6161 // rotate the quad around the up axis vector, this is made
6162 // especially easy by the fact we know the quad is flat,
6163 // so we only have to subtract the center position and
6164 // measure distance along the right vector, and then
6165 // multiply that by the newright vector and add back the
6167 // we also need to subtract the old position to undo the
6168 // displacement from the center, which we do with a
6169 // DotProduct, the subtraction/addition of center is also
6170 // optimized into DotProducts here
6171 l = DotProduct(right, center);
6172 for (i = 0;i < 4;i++)
6174 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6175 f = DotProduct(right, v1) - l;
6176 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6179 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);
6180 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);
6182 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6183 rsurface.vertex3f_bufferobject = 0;
6184 rsurface.vertex3f_bufferoffset = 0;
6185 rsurface.svector3f = rsurface.array_deformedsvector3f;
6186 rsurface.svector3f_bufferobject = 0;
6187 rsurface.svector3f_bufferoffset = 0;
6188 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6189 rsurface.tvector3f_bufferobject = 0;
6190 rsurface.tvector3f_bufferoffset = 0;
6191 rsurface.normal3f = rsurface.array_deformednormal3f;
6192 rsurface.normal3f_bufferobject = 0;
6193 rsurface.normal3f_bufferoffset = 0;
6195 case Q3DEFORM_NORMAL:
6196 // deform the normals to make reflections wavey
6197 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6199 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6200 for (j = 0;j < surface->num_vertices;j++)
6203 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6204 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6205 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6206 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6207 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6208 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6209 VectorNormalize(normal);
6211 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);
6213 rsurface.svector3f = rsurface.array_deformedsvector3f;
6214 rsurface.svector3f_bufferobject = 0;
6215 rsurface.svector3f_bufferoffset = 0;
6216 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6217 rsurface.tvector3f_bufferobject = 0;
6218 rsurface.tvector3f_bufferoffset = 0;
6219 rsurface.normal3f = rsurface.array_deformednormal3f;
6220 rsurface.normal3f_bufferobject = 0;
6221 rsurface.normal3f_bufferoffset = 0;
6224 // deform vertex array to make wavey water and flags and such
6225 waveparms[0] = deform->waveparms[0];
6226 waveparms[1] = deform->waveparms[1];
6227 waveparms[2] = deform->waveparms[2];
6228 waveparms[3] = deform->waveparms[3];
6229 // this is how a divisor of vertex influence on deformation
6230 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6231 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6232 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6234 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6235 for (j = 0;j < surface->num_vertices;j++)
6237 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6238 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6239 // if the wavefunc depends on time, evaluate it per-vertex
6242 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6243 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6245 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6248 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6249 rsurface.vertex3f_bufferobject = 0;
6250 rsurface.vertex3f_bufferoffset = 0;
6252 case Q3DEFORM_BULGE:
6253 // deform vertex array to make the surface have moving bulges
6254 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6256 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6257 for (j = 0;j < surface->num_vertices;j++)
6259 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6260 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6263 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6264 rsurface.vertex3f_bufferobject = 0;
6265 rsurface.vertex3f_bufferoffset = 0;
6268 // deform vertex array
6269 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6270 VectorScale(deform->parms, scale, waveparms);
6271 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6273 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6274 for (j = 0;j < surface->num_vertices;j++)
6275 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6277 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6278 rsurface.vertex3f_bufferobject = 0;
6279 rsurface.vertex3f_bufferoffset = 0;
6283 // generate texcoords based on the chosen texcoord source
6284 switch(rsurface.texture->tcgen.tcgen)
6287 case Q3TCGEN_TEXTURE:
6288 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6289 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6290 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6292 case Q3TCGEN_LIGHTMAP:
6293 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6294 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6295 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6297 case Q3TCGEN_VECTOR:
6298 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6300 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6301 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)
6303 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6304 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6307 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6308 rsurface.texcoordtexture2f_bufferobject = 0;
6309 rsurface.texcoordtexture2f_bufferoffset = 0;
6311 case Q3TCGEN_ENVIRONMENT:
6312 // make environment reflections using a spheremap
6313 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6315 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6316 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6317 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6318 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6319 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6321 // identical to Q3A's method, but executed in worldspace so
6322 // carried models can be shiny too
6324 float viewer[3], d, reflected[3], worldreflected[3];
6326 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6327 // VectorNormalize(viewer);
6329 d = DotProduct(normal, viewer);
6331 reflected[0] = normal[0]*2*d - viewer[0];
6332 reflected[1] = normal[1]*2*d - viewer[1];
6333 reflected[2] = normal[2]*2*d - viewer[2];
6334 // note: this is proportinal to viewer, so we can normalize later
6336 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6337 VectorNormalize(worldreflected);
6339 // note: this sphere map only uses world x and z!
6340 // so positive and negative y will LOOK THE SAME.
6341 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6342 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6345 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6346 rsurface.texcoordtexture2f_bufferobject = 0;
6347 rsurface.texcoordtexture2f_bufferoffset = 0;
6350 // the only tcmod that needs software vertex processing is turbulent, so
6351 // check for it here and apply the changes if needed
6352 // and we only support that as the first one
6353 // (handling a mixture of turbulent and other tcmods would be problematic
6354 // without punting it entirely to a software path)
6355 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6357 amplitude = rsurface.texture->tcmods[0].parms[1];
6358 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6359 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6361 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6362 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)
6364 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6365 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6368 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6369 rsurface.texcoordtexture2f_bufferobject = 0;
6370 rsurface.texcoordtexture2f_bufferoffset = 0;
6372 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6373 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6374 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6375 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6378 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6381 const msurface_t *surface = texturesurfacelist[0];
6382 const msurface_t *surface2;
6387 // TODO: lock all array ranges before render, rather than on each surface
6388 if (texturenumsurfaces == 1)
6390 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6391 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);
6393 else if (r_batchmode.integer == 2)
6395 #define MAXBATCHTRIANGLES 4096
6396 int batchtriangles = 0;
6397 int batchelements[MAXBATCHTRIANGLES*3];
6398 for (i = 0;i < texturenumsurfaces;i = j)
6400 surface = texturesurfacelist[i];
6402 if (surface->num_triangles > MAXBATCHTRIANGLES)
6404 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);
6407 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6408 batchtriangles = surface->num_triangles;
6409 firstvertex = surface->num_firstvertex;
6410 endvertex = surface->num_firstvertex + surface->num_vertices;
6411 for (;j < texturenumsurfaces;j++)
6413 surface2 = texturesurfacelist[j];
6414 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6416 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6417 batchtriangles += surface2->num_triangles;
6418 firstvertex = min(firstvertex, surface2->num_firstvertex);
6419 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6421 surface2 = texturesurfacelist[j-1];
6422 numvertices = endvertex - firstvertex;
6423 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6426 else if (r_batchmode.integer == 1)
6428 for (i = 0;i < texturenumsurfaces;i = j)
6430 surface = texturesurfacelist[i];
6431 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6432 if (texturesurfacelist[j] != surface2)
6434 surface2 = texturesurfacelist[j-1];
6435 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6436 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6437 GL_LockArrays(surface->num_firstvertex, numvertices);
6438 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6443 for (i = 0;i < texturenumsurfaces;i++)
6445 surface = texturesurfacelist[i];
6446 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6447 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);
6452 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6454 int i, planeindex, vertexindex;
6458 r_waterstate_waterplane_t *p, *bestp;
6459 msurface_t *surface;
6460 if (r_waterstate.renderingscene)
6462 for (i = 0;i < texturenumsurfaces;i++)
6464 surface = texturesurfacelist[i];
6465 if (lightmaptexunit >= 0)
6466 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6467 if (deluxemaptexunit >= 0)
6468 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6469 // pick the closest matching water plane
6472 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6475 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6477 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6478 d += fabs(PlaneDiff(vert, &p->plane));
6480 if (bestd > d || !bestp)
6488 if (refractiontexunit >= 0)
6489 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6490 if (reflectiontexunit >= 0)
6491 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6495 if (refractiontexunit >= 0)
6496 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6497 if (reflectiontexunit >= 0)
6498 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6500 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6501 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);
6505 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6509 const msurface_t *surface = texturesurfacelist[0];
6510 const msurface_t *surface2;
6515 // TODO: lock all array ranges before render, rather than on each surface
6516 if (texturenumsurfaces == 1)
6518 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6519 if (deluxemaptexunit >= 0)
6520 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6521 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6522 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);
6524 else if (r_batchmode.integer == 2)
6526 #define MAXBATCHTRIANGLES 4096
6527 int batchtriangles = 0;
6528 int batchelements[MAXBATCHTRIANGLES*3];
6529 for (i = 0;i < texturenumsurfaces;i = j)
6531 surface = texturesurfacelist[i];
6532 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6533 if (deluxemaptexunit >= 0)
6534 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6536 if (surface->num_triangles > MAXBATCHTRIANGLES)
6538 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);
6541 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6542 batchtriangles = surface->num_triangles;
6543 firstvertex = surface->num_firstvertex;
6544 endvertex = surface->num_firstvertex + surface->num_vertices;
6545 for (;j < texturenumsurfaces;j++)
6547 surface2 = texturesurfacelist[j];
6548 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6550 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6551 batchtriangles += surface2->num_triangles;
6552 firstvertex = min(firstvertex, surface2->num_firstvertex);
6553 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6555 surface2 = texturesurfacelist[j-1];
6556 numvertices = endvertex - firstvertex;
6557 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6560 else if (r_batchmode.integer == 1)
6563 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6564 for (i = 0;i < texturenumsurfaces;i = j)
6566 surface = texturesurfacelist[i];
6567 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6568 if (texturesurfacelist[j] != surface2)
6570 Con_Printf(" %i", j - i);
6573 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6575 for (i = 0;i < texturenumsurfaces;i = j)
6577 surface = texturesurfacelist[i];
6578 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6579 if (deluxemaptexunit >= 0)
6580 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6581 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6582 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6585 Con_Printf(" %i", j - i);
6587 surface2 = texturesurfacelist[j-1];
6588 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6589 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6590 GL_LockArrays(surface->num_firstvertex, numvertices);
6591 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6599 for (i = 0;i < texturenumsurfaces;i++)
6601 surface = texturesurfacelist[i];
6602 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6603 if (deluxemaptexunit >= 0)
6604 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6605 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6606 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);
6611 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6614 int texturesurfaceindex;
6615 if (r_showsurfaces.integer == 2)
6617 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6619 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6620 for (j = 0;j < surface->num_triangles;j++)
6622 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6623 GL_Color(f, f, f, 1);
6624 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6630 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6632 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6633 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6634 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);
6635 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6636 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);
6641 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6643 int texturesurfaceindex;
6646 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6648 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6649 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)
6657 rsurface.lightmapcolor4f = rsurface.array_color4f;
6658 rsurface.lightmapcolor4f_bufferobject = 0;
6659 rsurface.lightmapcolor4f_bufferoffset = 0;
6662 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6664 int texturesurfaceindex;
6668 if (rsurface.lightmapcolor4f)
6670 // generate color arrays for the surfaces in this list
6671 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6673 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6674 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)
6676 f = RSurf_FogVertex(v);
6686 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6688 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6689 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)
6691 f = RSurf_FogVertex(v);
6699 rsurface.lightmapcolor4f = rsurface.array_color4f;
6700 rsurface.lightmapcolor4f_bufferobject = 0;
6701 rsurface.lightmapcolor4f_bufferoffset = 0;
6704 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6706 int texturesurfaceindex;
6710 if (!rsurface.lightmapcolor4f)
6712 // generate color arrays for the surfaces in this list
6713 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6715 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6716 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)
6718 f = RSurf_FogVertex(v);
6719 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6720 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6721 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6725 rsurface.lightmapcolor4f = rsurface.array_color4f;
6726 rsurface.lightmapcolor4f_bufferobject = 0;
6727 rsurface.lightmapcolor4f_bufferoffset = 0;
6730 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6732 int texturesurfaceindex;
6735 if (!rsurface.lightmapcolor4f)
6737 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6739 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6740 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)
6748 rsurface.lightmapcolor4f = rsurface.array_color4f;
6749 rsurface.lightmapcolor4f_bufferobject = 0;
6750 rsurface.lightmapcolor4f_bufferoffset = 0;
6753 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6755 int texturesurfaceindex;
6758 if (!rsurface.lightmapcolor4f)
6760 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6762 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6763 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)
6765 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6766 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6767 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6771 rsurface.lightmapcolor4f = rsurface.array_color4f;
6772 rsurface.lightmapcolor4f_bufferobject = 0;
6773 rsurface.lightmapcolor4f_bufferoffset = 0;
6776 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6779 rsurface.lightmapcolor4f = NULL;
6780 rsurface.lightmapcolor4f_bufferobject = 0;
6781 rsurface.lightmapcolor4f_bufferoffset = 0;
6782 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6783 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6784 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6785 GL_Color(r, g, b, a);
6786 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6789 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6791 // TODO: optimize applyfog && applycolor case
6792 // just apply fog if necessary, and tint the fog color array if necessary
6793 rsurface.lightmapcolor4f = NULL;
6794 rsurface.lightmapcolor4f_bufferobject = 0;
6795 rsurface.lightmapcolor4f_bufferoffset = 0;
6796 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6797 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6798 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6799 GL_Color(r, g, b, a);
6800 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6803 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6805 int texturesurfaceindex;
6809 if (texturesurfacelist[0]->lightmapinfo)
6811 // generate color arrays for the surfaces in this list
6812 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6814 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6815 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6817 if (surface->lightmapinfo->samples)
6819 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6820 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6821 VectorScale(lm, scale, c);
6822 if (surface->lightmapinfo->styles[1] != 255)
6824 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6826 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6827 VectorMA(c, scale, lm, c);
6828 if (surface->lightmapinfo->styles[2] != 255)
6831 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6832 VectorMA(c, scale, lm, c);
6833 if (surface->lightmapinfo->styles[3] != 255)
6836 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6837 VectorMA(c, scale, lm, c);
6847 rsurface.lightmapcolor4f = rsurface.array_color4f;
6848 rsurface.lightmapcolor4f_bufferobject = 0;
6849 rsurface.lightmapcolor4f_bufferoffset = 0;
6853 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6854 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6855 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6857 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6858 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6859 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6860 GL_Color(r, g, b, a);
6861 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6864 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6866 int texturesurfaceindex;
6869 float *v, *c, *c2, alpha;
6870 vec3_t ambientcolor;
6871 vec3_t diffusecolor;
6875 VectorCopy(rsurface.modellight_lightdir, lightdir);
6876 f = 0.5f * r_refdef.lightmapintensity;
6877 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6878 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6879 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6880 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6881 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6882 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6884 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6886 // generate color arrays for the surfaces in this list
6887 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6889 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6890 int numverts = surface->num_vertices;
6891 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6892 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6893 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6894 // q3-style directional shading
6895 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6897 if ((f = DotProduct(c2, lightdir)) > 0)
6898 VectorMA(ambientcolor, f, diffusecolor, c);
6900 VectorCopy(ambientcolor, c);
6908 rsurface.lightmapcolor4f = rsurface.array_color4f;
6909 rsurface.lightmapcolor4f_bufferobject = 0;
6910 rsurface.lightmapcolor4f_bufferoffset = 0;
6911 *applycolor = false;
6915 *r = ambientcolor[0];
6916 *g = ambientcolor[1];
6917 *b = ambientcolor[2];
6918 rsurface.lightmapcolor4f = NULL;
6919 rsurface.lightmapcolor4f_bufferobject = 0;
6920 rsurface.lightmapcolor4f_bufferoffset = 0;
6924 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6926 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6927 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6928 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6929 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6930 GL_Color(r, g, b, a);
6931 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6934 void RSurf_SetupDepthAndCulling(void)
6936 // submodels are biased to avoid z-fighting with world surfaces that they
6937 // may be exactly overlapping (avoids z-fighting artifacts on certain
6938 // doors and things in Quake maps)
6939 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6940 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6941 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6942 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6945 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6947 // transparent sky would be ridiculous
6948 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6950 R_SetupGenericShader(false);
6953 skyrendernow = false;
6954 // we have to force off the water clipping plane while rendering sky
6958 // restore entity matrix
6959 R_Mesh_Matrix(&rsurface.matrix);
6961 RSurf_SetupDepthAndCulling();
6963 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6964 // skymasking on them, and Quake3 never did sky masking (unlike
6965 // software Quake and software Quake2), so disable the sky masking
6966 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6967 // and skymasking also looks very bad when noclipping outside the
6968 // level, so don't use it then either.
6969 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6971 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6972 R_Mesh_ColorPointer(NULL, 0, 0);
6973 R_Mesh_ResetTextureState();
6974 if (skyrendermasked)
6976 R_SetupDepthOrShadowShader();
6977 // depth-only (masking)
6978 GL_ColorMask(0,0,0,0);
6979 // just to make sure that braindead drivers don't draw
6980 // anything despite that colormask...
6981 GL_BlendFunc(GL_ZERO, GL_ONE);
6985 R_SetupGenericShader(false);
6987 GL_BlendFunc(GL_ONE, GL_ZERO);
6989 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6990 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6991 if (skyrendermasked)
6992 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6994 R_Mesh_ResetTextureState();
6995 GL_Color(1, 1, 1, 1);
6998 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7000 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7003 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7004 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7005 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7006 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7007 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7008 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7009 if (rsurface.texture->backgroundcurrentskinframe)
7011 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7012 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7013 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7014 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7016 if(rsurface.texture->colormapping)
7018 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7019 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7021 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7022 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7023 R_Mesh_ColorPointer(NULL, 0, 0);
7025 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7027 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7029 // render background
7030 GL_BlendFunc(GL_ONE, GL_ZERO);
7032 GL_AlphaTest(false);
7034 GL_Color(1, 1, 1, 1);
7035 R_Mesh_ColorPointer(NULL, 0, 0);
7037 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7038 if (r_glsl_permutation)
7040 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7041 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7042 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7043 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7044 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7045 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7046 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);
7048 GL_LockArrays(0, 0);
7050 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7051 GL_DepthMask(false);
7052 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7053 R_Mesh_ColorPointer(NULL, 0, 0);
7055 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7056 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7057 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7060 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7061 if (!r_glsl_permutation)
7064 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7065 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7066 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7067 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7068 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7069 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7071 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7073 GL_BlendFunc(GL_ONE, GL_ZERO);
7075 GL_AlphaTest(false);
7079 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7080 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7081 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7084 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7086 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7087 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);
7089 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7093 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7094 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);
7096 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7098 GL_LockArrays(0, 0);
7101 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7103 // OpenGL 1.3 path - anything not completely ancient
7104 int texturesurfaceindex;
7105 qboolean applycolor;
7109 const texturelayer_t *layer;
7110 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7112 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7115 int layertexrgbscale;
7116 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7118 if (layerindex == 0)
7122 GL_AlphaTest(false);
7123 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7126 GL_DepthMask(layer->depthmask && writedepth);
7127 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7128 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7130 layertexrgbscale = 4;
7131 VectorScale(layer->color, 0.25f, layercolor);
7133 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7135 layertexrgbscale = 2;
7136 VectorScale(layer->color, 0.5f, layercolor);
7140 layertexrgbscale = 1;
7141 VectorScale(layer->color, 1.0f, layercolor);
7143 layercolor[3] = layer->color[3];
7144 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7145 R_Mesh_ColorPointer(NULL, 0, 0);
7146 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7147 switch (layer->type)
7149 case TEXTURELAYERTYPE_LITTEXTURE:
7150 memset(&m, 0, sizeof(m));
7151 m.tex[0] = R_GetTexture(r_texture_white);
7152 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7153 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7154 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7155 m.tex[1] = R_GetTexture(layer->texture);
7156 m.texmatrix[1] = layer->texmatrix;
7157 m.texrgbscale[1] = layertexrgbscale;
7158 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7159 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7160 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7161 R_Mesh_TextureState(&m);
7162 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7163 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7164 else if (rsurface.uselightmaptexture)
7165 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7167 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7169 case TEXTURELAYERTYPE_TEXTURE:
7170 memset(&m, 0, sizeof(m));
7171 m.tex[0] = R_GetTexture(layer->texture);
7172 m.texmatrix[0] = layer->texmatrix;
7173 m.texrgbscale[0] = layertexrgbscale;
7174 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7175 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7176 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7177 R_Mesh_TextureState(&m);
7178 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7180 case TEXTURELAYERTYPE_FOG:
7181 memset(&m, 0, sizeof(m));
7182 m.texrgbscale[0] = layertexrgbscale;
7185 m.tex[0] = R_GetTexture(layer->texture);
7186 m.texmatrix[0] = layer->texmatrix;
7187 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7188 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7189 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7191 R_Mesh_TextureState(&m);
7192 // generate a color array for the fog pass
7193 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7194 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7198 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7199 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)
7201 f = 1 - RSurf_FogVertex(v);
7202 c[0] = layercolor[0];
7203 c[1] = layercolor[1];
7204 c[2] = layercolor[2];
7205 c[3] = f * layercolor[3];
7208 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7211 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7213 GL_LockArrays(0, 0);
7216 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7218 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7219 GL_AlphaTest(false);
7223 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7225 // OpenGL 1.1 - crusty old voodoo path
7226 int texturesurfaceindex;
7230 const texturelayer_t *layer;
7231 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7233 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7235 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7237 if (layerindex == 0)
7241 GL_AlphaTest(false);
7242 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7245 GL_DepthMask(layer->depthmask && writedepth);
7246 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7247 R_Mesh_ColorPointer(NULL, 0, 0);
7248 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7249 switch (layer->type)
7251 case TEXTURELAYERTYPE_LITTEXTURE:
7252 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7254 // two-pass lit texture with 2x rgbscale
7255 // first the lightmap pass
7256 memset(&m, 0, sizeof(m));
7257 m.tex[0] = R_GetTexture(r_texture_white);
7258 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7259 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7260 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7261 R_Mesh_TextureState(&m);
7262 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7263 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7264 else if (rsurface.uselightmaptexture)
7265 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7267 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7268 GL_LockArrays(0, 0);
7269 // then apply the texture to it
7270 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7271 memset(&m, 0, sizeof(m));
7272 m.tex[0] = R_GetTexture(layer->texture);
7273 m.texmatrix[0] = layer->texmatrix;
7274 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7275 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7276 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7277 R_Mesh_TextureState(&m);
7278 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);
7282 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7283 memset(&m, 0, sizeof(m));
7284 m.tex[0] = R_GetTexture(layer->texture);
7285 m.texmatrix[0] = layer->texmatrix;
7286 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7287 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7288 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7289 R_Mesh_TextureState(&m);
7290 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7291 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);
7293 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);
7296 case TEXTURELAYERTYPE_TEXTURE:
7297 // singletexture unlit texture with transparency support
7298 memset(&m, 0, sizeof(m));
7299 m.tex[0] = R_GetTexture(layer->texture);
7300 m.texmatrix[0] = layer->texmatrix;
7301 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7302 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7303 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7304 R_Mesh_TextureState(&m);
7305 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);
7307 case TEXTURELAYERTYPE_FOG:
7308 // singletexture fogging
7309 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7312 memset(&m, 0, sizeof(m));
7313 m.tex[0] = R_GetTexture(layer->texture);
7314 m.texmatrix[0] = layer->texmatrix;
7315 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7316 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7317 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7318 R_Mesh_TextureState(&m);
7321 R_Mesh_ResetTextureState();
7322 // generate a color array for the fog pass
7323 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7327 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7328 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)
7330 f = 1 - RSurf_FogVertex(v);
7331 c[0] = layer->color[0];
7332 c[1] = layer->color[1];
7333 c[2] = layer->color[2];
7334 c[3] = f * layer->color[3];
7337 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7340 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7342 GL_LockArrays(0, 0);
7345 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7347 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7348 GL_AlphaTest(false);
7352 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7356 GL_AlphaTest(false);
7357 R_Mesh_ColorPointer(NULL, 0, 0);
7358 R_Mesh_ResetTextureState();
7359 R_SetupGenericShader(false);
7361 if(rsurface.texture && rsurface.texture->currentskinframe)
7363 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7364 c[3] *= rsurface.texture->currentalpha;
7374 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7376 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7377 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7378 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7381 // brighten it up (as texture value 127 means "unlit")
7382 c[0] *= 2 * r_refdef.view.colorscale;
7383 c[1] *= 2 * r_refdef.view.colorscale;
7384 c[2] *= 2 * r_refdef.view.colorscale;
7386 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7387 c[3] *= r_wateralpha.value;
7389 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7391 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7392 GL_DepthMask(false);
7394 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7396 GL_BlendFunc(GL_ONE, GL_ONE);
7397 GL_DepthMask(false);
7399 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7401 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7402 GL_DepthMask(false);
7404 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7406 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7407 GL_DepthMask(false);
7411 GL_BlendFunc(GL_ONE, GL_ZERO);
7412 GL_DepthMask(writedepth);
7415 rsurface.lightmapcolor4f = NULL;
7417 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7419 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7421 rsurface.lightmapcolor4f = NULL;
7422 rsurface.lightmapcolor4f_bufferobject = 0;
7423 rsurface.lightmapcolor4f_bufferoffset = 0;
7425 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7427 qboolean applycolor = true;
7430 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7432 r_refdef.lightmapintensity = 1;
7433 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7434 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7438 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7440 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7441 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7442 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7445 if(!rsurface.lightmapcolor4f)
7446 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7448 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7449 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7450 if(r_refdef.fogenabled)
7451 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7453 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7454 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7457 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7460 RSurf_SetupDepthAndCulling();
7461 if (r_showsurfaces.integer == 3)
7462 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7463 else if (r_glsl.integer && gl_support_fragment_shader)
7464 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7465 else if (gl_combine.integer && r_textureunits.integer >= 2)
7466 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7468 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7472 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7475 RSurf_SetupDepthAndCulling();
7476 if (r_showsurfaces.integer == 3)
7477 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7478 else if (r_glsl.integer && gl_support_fragment_shader)
7479 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7480 else if (gl_combine.integer && r_textureunits.integer >= 2)
7481 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7483 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7487 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7490 int texturenumsurfaces, endsurface;
7492 msurface_t *surface;
7493 msurface_t *texturesurfacelist[1024];
7495 // if the model is static it doesn't matter what value we give for
7496 // wantnormals and wanttangents, so this logic uses only rules applicable
7497 // to a model, knowing that they are meaningless otherwise
7498 if (ent == r_refdef.scene.worldentity)
7499 RSurf_ActiveWorldEntity();
7500 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7501 RSurf_ActiveModelEntity(ent, false, false);
7503 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7505 for (i = 0;i < numsurfaces;i = j)
7508 surface = rsurface.modelsurfaces + surfacelist[i];
7509 texture = surface->texture;
7510 rsurface.texture = R_GetCurrentTexture(texture);
7511 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7512 // scan ahead until we find a different texture
7513 endsurface = min(i + 1024, numsurfaces);
7514 texturenumsurfaces = 0;
7515 texturesurfacelist[texturenumsurfaces++] = surface;
7516 for (;j < endsurface;j++)
7518 surface = rsurface.modelsurfaces + surfacelist[j];
7519 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7521 texturesurfacelist[texturenumsurfaces++] = surface;
7523 // render the range of surfaces
7524 if (ent == r_refdef.scene.worldentity)
7525 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7527 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7529 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7530 GL_AlphaTest(false);
7533 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7535 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7539 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7541 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7543 RSurf_SetupDepthAndCulling();
7544 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7545 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7547 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7549 RSurf_SetupDepthAndCulling();
7550 GL_AlphaTest(false);
7551 R_Mesh_ColorPointer(NULL, 0, 0);
7552 R_Mesh_ResetTextureState();
7553 R_SetupGenericShader(false);
7554 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7556 GL_BlendFunc(GL_ONE, GL_ZERO);
7557 GL_Color(0, 0, 0, 1);
7558 GL_DepthTest(writedepth);
7559 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7561 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7563 RSurf_SetupDepthAndCulling();
7564 GL_AlphaTest(false);
7565 R_Mesh_ColorPointer(NULL, 0, 0);
7566 R_Mesh_ResetTextureState();
7567 R_SetupGenericShader(false);
7568 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7570 GL_BlendFunc(GL_ONE, GL_ZERO);
7572 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7574 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7575 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7576 else if (!rsurface.texture->currentnumlayers)
7578 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7580 // transparent surfaces get pushed off into the transparent queue
7581 int surfacelistindex;
7582 const msurface_t *surface;
7583 vec3_t tempcenter, center;
7584 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7586 surface = texturesurfacelist[surfacelistindex];
7587 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7588 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7589 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7590 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7591 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7596 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7597 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7602 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7606 // break the surface list down into batches by texture and use of lightmapping
7607 for (i = 0;i < numsurfaces;i = j)
7610 // texture is the base texture pointer, rsurface.texture is the
7611 // current frame/skin the texture is directing us to use (for example
7612 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7613 // use skin 1 instead)
7614 texture = surfacelist[i]->texture;
7615 rsurface.texture = R_GetCurrentTexture(texture);
7616 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7617 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7619 // if this texture is not the kind we want, skip ahead to the next one
7620 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7624 // simply scan ahead until we find a different texture or lightmap state
7625 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7627 // render the range of surfaces
7628 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7632 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7637 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7639 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7641 RSurf_SetupDepthAndCulling();
7642 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7643 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7645 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7647 RSurf_SetupDepthAndCulling();
7648 GL_AlphaTest(false);
7649 R_Mesh_ColorPointer(NULL, 0, 0);
7650 R_Mesh_ResetTextureState();
7651 R_SetupGenericShader(false);
7652 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7654 GL_BlendFunc(GL_ONE, GL_ZERO);
7655 GL_Color(0, 0, 0, 1);
7656 GL_DepthTest(writedepth);
7657 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7659 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7661 RSurf_SetupDepthAndCulling();
7662 GL_AlphaTest(false);
7663 R_Mesh_ColorPointer(NULL, 0, 0);
7664 R_Mesh_ResetTextureState();
7665 R_SetupGenericShader(false);
7666 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7668 GL_BlendFunc(GL_ONE, GL_ZERO);
7670 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7672 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7673 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7674 else if (!rsurface.texture->currentnumlayers)
7676 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7678 // transparent surfaces get pushed off into the transparent queue
7679 int surfacelistindex;
7680 const msurface_t *surface;
7681 vec3_t tempcenter, center;
7682 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7684 surface = texturesurfacelist[surfacelistindex];
7685 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7686 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7687 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7688 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7689 if (queueentity->transparent_offset) // transparent offset
7691 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
7692 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
7693 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
7695 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7700 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7701 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7706 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7710 // break the surface list down into batches by texture and use of lightmapping
7711 for (i = 0;i < numsurfaces;i = j)
7714 // texture is the base texture pointer, rsurface.texture is the
7715 // current frame/skin the texture is directing us to use (for example
7716 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7717 // use skin 1 instead)
7718 texture = surfacelist[i]->texture;
7719 rsurface.texture = R_GetCurrentTexture(texture);
7720 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7721 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7723 // if this texture is not the kind we want, skip ahead to the next one
7724 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7728 // simply scan ahead until we find a different texture or lightmap state
7729 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7731 // render the range of surfaces
7732 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7736 float locboxvertex3f[6*4*3] =
7738 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7739 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7740 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7741 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7742 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7743 1,0,0, 0,0,0, 0,1,0, 1,1,0
7746 unsigned short locboxelements[6*2*3] =
7756 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7759 cl_locnode_t *loc = (cl_locnode_t *)ent;
7761 float vertex3f[6*4*3];
7763 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7764 GL_DepthMask(false);
7765 GL_DepthRange(0, 1);
7766 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7768 GL_CullFace(GL_NONE);
7769 R_Mesh_Matrix(&identitymatrix);
7771 R_Mesh_VertexPointer(vertex3f, 0, 0);
7772 R_Mesh_ColorPointer(NULL, 0, 0);
7773 R_Mesh_ResetTextureState();
7774 R_SetupGenericShader(false);
7777 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7778 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7779 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7780 surfacelist[0] < 0 ? 0.5f : 0.125f);
7782 if (VectorCompare(loc->mins, loc->maxs))
7784 VectorSet(size, 2, 2, 2);
7785 VectorMA(loc->mins, -0.5f, size, mins);
7789 VectorCopy(loc->mins, mins);
7790 VectorSubtract(loc->maxs, loc->mins, size);
7793 for (i = 0;i < 6*4*3;)
7794 for (j = 0;j < 3;j++, i++)
7795 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7797 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7800 void R_DrawLocs(void)
7803 cl_locnode_t *loc, *nearestloc;
7805 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7806 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7808 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7809 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7813 void R_DrawDebugModel(entity_render_t *ent)
7815 int i, j, k, l, flagsmask;
7816 const int *elements;
7818 msurface_t *surface;
7819 dp_model_t *model = ent->model;
7822 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7824 R_Mesh_ColorPointer(NULL, 0, 0);
7825 R_Mesh_ResetTextureState();
7826 R_SetupGenericShader(false);
7827 GL_DepthRange(0, 1);
7828 GL_DepthTest(!r_showdisabledepthtest.integer);
7829 GL_DepthMask(false);
7830 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7832 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7834 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7835 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7837 if (brush->colbrushf && brush->colbrushf->numtriangles)
7839 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7840 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);
7841 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7844 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7846 if (surface->num_collisiontriangles)
7848 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7849 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);
7850 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7855 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7857 if (r_showtris.integer || r_shownormals.integer)
7859 if (r_showdisabledepthtest.integer)
7861 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7862 GL_DepthMask(false);
7866 GL_BlendFunc(GL_ONE, GL_ZERO);
7869 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7871 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7873 rsurface.texture = R_GetCurrentTexture(surface->texture);
7874 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7876 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7877 if (r_showtris.value > 0)
7879 if (!rsurface.texture->currentlayers->depthmask)
7880 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7881 else if (ent == r_refdef.scene.worldentity)
7882 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7884 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7885 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7886 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7887 R_Mesh_ColorPointer(NULL, 0, 0);
7888 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7889 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7890 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7891 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);
7892 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7895 if (r_shownormals.value < 0)
7898 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7900 VectorCopy(rsurface.vertex3f + l * 3, v);
7901 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7902 qglVertex3f(v[0], v[1], v[2]);
7903 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7904 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7905 qglVertex3f(v[0], v[1], v[2]);
7910 if (r_shownormals.value > 0)
7913 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7915 VectorCopy(rsurface.vertex3f + l * 3, v);
7916 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7917 qglVertex3f(v[0], v[1], v[2]);
7918 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7919 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7920 qglVertex3f(v[0], v[1], v[2]);
7925 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7927 VectorCopy(rsurface.vertex3f + l * 3, v);
7928 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7929 qglVertex3f(v[0], v[1], v[2]);
7930 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7931 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7932 qglVertex3f(v[0], v[1], v[2]);
7937 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7939 VectorCopy(rsurface.vertex3f + l * 3, v);
7940 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7941 qglVertex3f(v[0], v[1], v[2]);
7942 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7943 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7944 qglVertex3f(v[0], v[1], v[2]);
7951 rsurface.texture = NULL;
7955 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7956 int r_maxsurfacelist = 0;
7957 msurface_t **r_surfacelist = NULL;
7958 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7960 int i, j, endj, f, flagsmask;
7962 dp_model_t *model = r_refdef.scene.worldmodel;
7963 msurface_t *surfaces;
7964 unsigned char *update;
7965 int numsurfacelist = 0;
7969 if (r_maxsurfacelist < model->num_surfaces)
7971 r_maxsurfacelist = model->num_surfaces;
7973 Mem_Free(r_surfacelist);
7974 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7977 RSurf_ActiveWorldEntity();
7979 surfaces = model->data_surfaces;
7980 update = model->brushq1.lightmapupdateflags;
7982 // update light styles on this submodel
7983 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7985 model_brush_lightstyleinfo_t *style;
7986 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7988 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7990 int *list = style->surfacelist;
7991 style->value = r_refdef.scene.lightstylevalue[style->style];
7992 for (j = 0;j < style->numsurfaces;j++)
7993 update[list[j]] = true;
7998 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8002 R_DrawDebugModel(r_refdef.scene.worldentity);
8003 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8009 rsurface.uselightmaptexture = false;
8010 rsurface.texture = NULL;
8011 rsurface.rtlight = NULL;
8013 // add visible surfaces to draw list
8014 for (i = 0;i < model->nummodelsurfaces;i++)
8016 j = model->sortedmodelsurfaces[i];
8017 if (r_refdef.viewcache.world_surfacevisible[j])
8018 r_surfacelist[numsurfacelist++] = surfaces + j;
8020 // update lightmaps if needed
8022 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8023 if (r_refdef.viewcache.world_surfacevisible[j])
8025 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8026 // don't do anything if there were no surfaces
8027 if (!numsurfacelist)
8029 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8032 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8033 GL_AlphaTest(false);
8035 // add to stats if desired
8036 if (r_speeds.integer && !skysurfaces && !depthonly)
8038 r_refdef.stats.world_surfaces += numsurfacelist;
8039 for (j = 0;j < numsurfacelist;j++)
8040 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8042 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8045 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8047 int i, j, endj, f, flagsmask;
8049 dp_model_t *model = ent->model;
8050 msurface_t *surfaces;
8051 unsigned char *update;
8052 int numsurfacelist = 0;
8056 if (r_maxsurfacelist < model->num_surfaces)
8058 r_maxsurfacelist = model->num_surfaces;
8060 Mem_Free(r_surfacelist);
8061 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8064 // if the model is static it doesn't matter what value we give for
8065 // wantnormals and wanttangents, so this logic uses only rules applicable
8066 // to a model, knowing that they are meaningless otherwise
8067 if (ent == r_refdef.scene.worldentity)
8068 RSurf_ActiveWorldEntity();
8069 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8070 RSurf_ActiveModelEntity(ent, false, false);
8072 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8074 surfaces = model->data_surfaces;
8075 update = model->brushq1.lightmapupdateflags;
8077 // update light styles
8078 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8080 model_brush_lightstyleinfo_t *style;
8081 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8083 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8085 int *list = style->surfacelist;
8086 style->value = r_refdef.scene.lightstylevalue[style->style];
8087 for (j = 0;j < style->numsurfaces;j++)
8088 update[list[j]] = true;
8093 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8097 R_DrawDebugModel(ent);
8098 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8104 rsurface.uselightmaptexture = false;
8105 rsurface.texture = NULL;
8106 rsurface.rtlight = NULL;
8108 // add visible surfaces to draw list
8109 for (i = 0;i < model->nummodelsurfaces;i++)
8110 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8111 // don't do anything if there were no surfaces
8112 if (!numsurfacelist)
8114 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8117 // update lightmaps if needed
8119 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8121 R_BuildLightMap(ent, surfaces + j);
8122 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8123 GL_AlphaTest(false);
8125 // add to stats if desired
8126 if (r_speeds.integer && !skysurfaces && !depthonly)
8128 r_refdef.stats.entities_surfaces += numsurfacelist;
8129 for (j = 0;j < numsurfacelist;j++)
8130 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8132 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity