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 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
49 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"};
50 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
51 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
52 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
53 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)"};
54 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
55 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
56 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"};
57 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"};
58 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
59 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"};
60 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"};
61 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"};
62 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
63 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
64 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
65 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
66 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
67 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
68 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
69 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
70 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
71 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
72 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
73 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
74 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."};
75 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
76 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
77 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
78 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."};
79 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
80 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
81 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"};
82 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"};
83 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
84 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
86 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
87 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
88 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
89 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
90 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
91 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
92 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
93 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
95 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)"};
97 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
98 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)"};
99 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
100 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
101 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
102 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
103 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)"};
104 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)"};
105 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)"};
106 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)"};
107 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)"};
109 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)"};
110 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
111 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"};
112 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
113 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
115 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
116 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
117 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
118 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
120 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
121 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
122 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
123 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
124 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
125 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
126 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
128 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
129 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
130 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
131 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)"};
133 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"};
135 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"};
137 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
139 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
140 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
141 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"};
142 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
143 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
144 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
145 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
147 extern cvar_t v_glslgamma;
149 extern qboolean v_flipped_state;
151 static struct r_bloomstate_s
156 int bloomwidth, bloomheight;
158 int screentexturewidth, screentextureheight;
159 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
161 int bloomtexturewidth, bloomtextureheight;
162 rtexture_t *texture_bloom;
164 // arrays for rendering the screen passes
165 float screentexcoord2f[8];
166 float bloomtexcoord2f[8];
167 float offsettexcoord2f[8];
169 r_viewport_t viewport;
173 r_waterstate_t r_waterstate;
175 /// shadow volume bsp struct with automatically growing nodes buffer
178 rtexture_t *r_texture_blanknormalmap;
179 rtexture_t *r_texture_white;
180 rtexture_t *r_texture_grey128;
181 rtexture_t *r_texture_black;
182 rtexture_t *r_texture_notexture;
183 rtexture_t *r_texture_whitecube;
184 rtexture_t *r_texture_normalizationcube;
185 rtexture_t *r_texture_fogattenuation;
186 rtexture_t *r_texture_gammaramps;
187 unsigned int r_texture_gammaramps_serial;
188 //rtexture_t *r_texture_fogintensity;
190 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
191 unsigned int r_numqueries;
192 unsigned int r_maxqueries;
194 typedef struct r_qwskincache_s
196 char name[MAX_QPATH];
197 skinframe_t *skinframe;
201 static r_qwskincache_t *r_qwskincache;
202 static int r_qwskincache_size;
204 /// vertex coordinates for a quad that covers the screen exactly
205 const float r_screenvertex3f[12] =
213 extern void R_DrawModelShadows(void);
215 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
218 for (i = 0;i < verts;i++)
229 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
232 for (i = 0;i < verts;i++)
242 // FIXME: move this to client?
245 if (gamemode == GAME_NEHAHRA)
247 Cvar_Set("gl_fogenable", "0");
248 Cvar_Set("gl_fogdensity", "0.2");
249 Cvar_Set("gl_fogred", "0.3");
250 Cvar_Set("gl_foggreen", "0.3");
251 Cvar_Set("gl_fogblue", "0.3");
253 r_refdef.fog_density = 0;
254 r_refdef.fog_red = 0;
255 r_refdef.fog_green = 0;
256 r_refdef.fog_blue = 0;
257 r_refdef.fog_alpha = 1;
258 r_refdef.fog_start = 0;
259 r_refdef.fog_end = 0;
262 static void R_BuildBlankTextures(void)
264 unsigned char data[4];
265 data[2] = 128; // normal X
266 data[1] = 128; // normal Y
267 data[0] = 255; // normal Z
268 data[3] = 128; // height
269 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
274 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
279 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
284 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
287 static void R_BuildNoTexture(void)
290 unsigned char pix[16][16][4];
291 // this makes a light grey/dark grey checkerboard texture
292 for (y = 0;y < 16;y++)
294 for (x = 0;x < 16;x++)
296 if ((y < 8) ^ (x < 8))
312 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
315 static void R_BuildWhiteCube(void)
317 unsigned char data[6*1*1*4];
318 memset(data, 255, sizeof(data));
319 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
322 static void R_BuildNormalizationCube(void)
326 vec_t s, t, intensity;
328 unsigned char data[6][NORMSIZE][NORMSIZE][4];
329 for (side = 0;side < 6;side++)
331 for (y = 0;y < NORMSIZE;y++)
333 for (x = 0;x < NORMSIZE;x++)
335 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
336 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
371 intensity = 127.0f / sqrt(DotProduct(v, v));
372 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
373 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
374 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
375 data[side][y][x][3] = 255;
379 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
382 static void R_BuildFogTexture(void)
386 unsigned char data1[FOGWIDTH][4];
387 //unsigned char data2[FOGWIDTH][4];
390 r_refdef.fogmasktable_start = r_refdef.fog_start;
391 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
392 r_refdef.fogmasktable_range = r_refdef.fogrange;
393 r_refdef.fogmasktable_density = r_refdef.fog_density;
395 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
396 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
398 d = (x * r - r_refdef.fogmasktable_start);
399 if(developer.integer >= 100)
400 Con_Printf("%f ", d);
402 if (r_fog_exp2.integer)
403 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
405 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
406 if(developer.integer >= 100)
407 Con_Printf(" : %f ", alpha);
408 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
409 if(developer.integer >= 100)
410 Con_Printf(" = %f\n", alpha);
411 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
414 for (x = 0;x < FOGWIDTH;x++)
416 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
421 //data2[x][0] = 255 - b;
422 //data2[x][1] = 255 - b;
423 //data2[x][2] = 255 - b;
426 if (r_texture_fogattenuation)
428 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
429 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
433 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);
434 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
438 static const char *builtinshaderstring =
439 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
440 "// written by Forest 'LordHavoc' Hale\n"
442 "// enable various extensions depending on permutation:\n"
444 "#ifdef USESHADOWMAPRECT\n"
445 "# extension GL_ARB_texture_rectangle : enable\n"
448 "#ifdef USESHADOWMAP2D\n"
449 "# ifdef GL_EXT_gpu_shader4\n"
450 "# extension GL_EXT_gpu_shader4 : enable\n"
452 "# ifdef GL_ARB_texture_gather\n"
453 "# extension GL_ARB_texture_gather : enable\n"
455 "# ifdef GL_AMD_texture_texture4\n"
456 "# extension GL_AMD_texture_texture4 : enable\n"
461 "#ifdef USESHADOWMAPCUBE\n"
462 "# extension GL_EXT_gpu_shader4 : enable\n"
465 "#ifdef USESHADOWSAMPLER\n"
466 "# extension GL_ARB_shadow : enable\n"
469 "// common definitions between vertex shader and fragment shader:\n"
471 "//#ifdef __GLSL_CG_DATA_TYPES\n"
472 "//# define myhalf half\n"
473 "//# define myhalf2 half2\n"
474 "//# define myhalf3half3\n"
475 "//# define myhalf4 half4\n"
477 "# define myhalf float\n"
478 "# define myhalf2 vec2\n"
479 "# define myhalf3 vec3\n"
480 "# define myhalf4 vec4\n"
483 "#ifdef MODE_DEPTH_OR_SHADOW\n"
485 "# ifdef VERTEX_SHADER\n"
488 " gl_Position = ftransform();\n"
493 "#ifdef MODE_SHOWDEPTH\n"
494 "# ifdef VERTEX_SHADER\n"
497 " gl_Position = ftransform();\n"
498 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
501 "# ifdef FRAGMENT_SHADER\n"
504 " gl_FragColor = gl_Color;\n"
508 "#else // !MODE_SHOWDEPTH\n"
510 "#ifdef MODE_POSTPROCESS\n"
511 "# ifdef VERTEX_SHADER\n"
514 " gl_FrontColor = gl_Color;\n"
515 " gl_Position = ftransform();\n"
516 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
518 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
522 "# ifdef FRAGMENT_SHADER\n"
524 "uniform sampler2D Texture_First;\n"
526 "uniform sampler2D Texture_Second;\n"
528 "#ifdef USEGAMMARAMPS\n"
529 "uniform sampler2D Texture_GammaRamps;\n"
531 "#ifdef USESATURATION\n"
532 "uniform float Saturation;\n"
534 "#ifdef USEVIEWTINT\n"
535 "uniform vec4 TintColor;\n"
537 "//uncomment these if you want to use them:\n"
538 "uniform vec4 UserVec1;\n"
539 "// uniform vec4 UserVec2;\n"
540 "// uniform vec4 UserVec3;\n"
541 "// uniform vec4 UserVec4;\n"
542 "// uniform float ClientTime;\n"
543 "uniform vec2 PixelSize;\n"
546 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
548 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
550 "#ifdef USEVIEWTINT\n"
551 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
554 "#ifdef USEPOSTPROCESSING\n"
555 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
556 "// 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"
557 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
558 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
559 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
560 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
561 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
562 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
565 "#ifdef USESATURATION\n"
566 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
567 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
568 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
569 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
572 "#ifdef USEGAMMARAMPS\n"
573 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
574 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
575 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
582 "#ifdef MODE_GENERIC\n"
583 "# ifdef VERTEX_SHADER\n"
586 " gl_FrontColor = gl_Color;\n"
587 "# ifdef USEDIFFUSE\n"
588 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
590 "# ifdef USESPECULAR\n"
591 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
593 " gl_Position = ftransform();\n"
596 "# ifdef FRAGMENT_SHADER\n"
598 "# ifdef USEDIFFUSE\n"
599 "uniform sampler2D Texture_First;\n"
601 "# ifdef USESPECULAR\n"
602 "uniform sampler2D Texture_Second;\n"
607 " gl_FragColor = gl_Color;\n"
608 "# ifdef USEDIFFUSE\n"
609 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
612 "# ifdef USESPECULAR\n"
613 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
615 "# ifdef USECOLORMAPPING\n"
616 " gl_FragColor *= tex2;\n"
619 " gl_FragColor += tex2;\n"
621 "# ifdef USEVERTEXTEXTUREBLEND\n"
622 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
627 "#else // !MODE_GENERIC\n"
629 "varying vec2 TexCoord;\n"
630 "#ifdef USEVERTEXTEXTUREBLEND\n"
631 "varying vec2 TexCoord2;\n"
633 "varying vec2 TexCoordLightmap;\n"
635 "#ifdef MODE_LIGHTSOURCE\n"
636 "varying vec3 CubeVector;\n"
639 "#ifdef MODE_LIGHTSOURCE\n"
640 "varying vec3 LightVector;\n"
642 "#ifdef MODE_LIGHTDIRECTION\n"
643 "varying vec3 LightVector;\n"
646 "varying vec3 EyeVector;\n"
648 "varying vec3 EyeVectorModelSpace;\n"
651 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
652 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
653 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
655 "#ifdef MODE_WATER\n"
656 "varying vec4 ModelViewProjectionPosition;\n"
658 "#ifdef MODE_REFRACTION\n"
659 "varying vec4 ModelViewProjectionPosition;\n"
661 "#ifdef USEREFLECTION\n"
662 "varying vec4 ModelViewProjectionPosition;\n"
669 "// vertex shader specific:\n"
670 "#ifdef VERTEX_SHADER\n"
672 "uniform vec3 LightPosition;\n"
673 "uniform vec3 EyePosition;\n"
674 "uniform vec3 LightDir;\n"
676 "// 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"
680 " gl_FrontColor = gl_Color;\n"
681 " // copy the surface texcoord\n"
682 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
683 "#ifdef USEVERTEXTEXTUREBLEND\n"
684 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
686 "#ifndef MODE_LIGHTSOURCE\n"
687 "# ifndef MODE_LIGHTDIRECTION\n"
688 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
692 "#ifdef MODE_LIGHTSOURCE\n"
693 " // transform vertex position into light attenuation/cubemap space\n"
694 " // (-1 to +1 across the light box)\n"
695 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
697 " // transform unnormalized light direction into tangent space\n"
698 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
699 " // normalize it per pixel)\n"
700 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
701 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
702 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
703 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
706 "#ifdef MODE_LIGHTDIRECTION\n"
707 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
708 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
709 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
712 " // transform unnormalized eye direction into tangent space\n"
714 " vec3 EyeVectorModelSpace;\n"
716 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
717 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
718 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
719 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
721 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
722 " VectorS = gl_MultiTexCoord1.xyz;\n"
723 " VectorT = gl_MultiTexCoord2.xyz;\n"
724 " VectorR = gl_MultiTexCoord3.xyz;\n"
727 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
728 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
729 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
730 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
733 "// transform vertex to camera space, using ftransform to match non-VS\n"
735 " gl_Position = ftransform();\n"
737 "#ifdef MODE_WATER\n"
738 " ModelViewProjectionPosition = gl_Position;\n"
740 "#ifdef MODE_REFRACTION\n"
741 " ModelViewProjectionPosition = gl_Position;\n"
743 "#ifdef USEREFLECTION\n"
744 " ModelViewProjectionPosition = gl_Position;\n"
748 "#endif // VERTEX_SHADER\n"
753 "// fragment shader specific:\n"
754 "#ifdef FRAGMENT_SHADER\n"
756 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
757 "uniform sampler2D Texture_Normal;\n"
758 "uniform sampler2D Texture_Color;\n"
759 "uniform sampler2D Texture_Gloss;\n"
760 "uniform sampler2D Texture_Glow;\n"
761 "uniform sampler2D Texture_SecondaryNormal;\n"
762 "uniform sampler2D Texture_SecondaryColor;\n"
763 "uniform sampler2D Texture_SecondaryGloss;\n"
764 "uniform sampler2D Texture_SecondaryGlow;\n"
765 "uniform sampler2D Texture_Pants;\n"
766 "uniform sampler2D Texture_Shirt;\n"
767 "uniform sampler2D Texture_FogMask;\n"
768 "uniform sampler2D Texture_Lightmap;\n"
769 "uniform sampler2D Texture_Deluxemap;\n"
770 "uniform sampler2D Texture_Refraction;\n"
771 "uniform sampler2D Texture_Reflection;\n"
772 "uniform sampler2D Texture_Attenuation;\n"
773 "uniform samplerCube Texture_Cube;\n"
775 "#define showshadowmap 0\n"
777 "#ifdef USESHADOWMAPRECT\n"
778 "# ifdef USESHADOWSAMPLER\n"
779 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
781 "uniform sampler2DRect Texture_ShadowMapRect;\n"
785 "#ifdef USESHADOWMAP2D\n"
786 "# ifdef USESHADOWSAMPLER\n"
787 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
789 "uniform sampler2D Texture_ShadowMap2D;\n"
793 "#ifdef USESHADOWMAPVSDCT\n"
794 "uniform samplerCube Texture_CubeProjection;\n"
797 "#ifdef USESHADOWMAPCUBE\n"
798 "# ifdef USESHADOWSAMPLER\n"
799 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
801 "uniform samplerCube Texture_ShadowMapCube;\n"
805 "uniform myhalf3 LightColor;\n"
806 "uniform myhalf3 AmbientColor;\n"
807 "uniform myhalf3 DiffuseColor;\n"
808 "uniform myhalf3 SpecularColor;\n"
809 "uniform myhalf3 Color_Pants;\n"
810 "uniform myhalf3 Color_Shirt;\n"
811 "uniform myhalf3 FogColor;\n"
813 "uniform myhalf4 TintColor;\n"
816 "//#ifdef MODE_WATER\n"
817 "uniform vec4 DistortScaleRefractReflect;\n"
818 "uniform vec4 ScreenScaleRefractReflect;\n"
819 "uniform vec4 ScreenCenterRefractReflect;\n"
820 "uniform myhalf4 RefractColor;\n"
821 "uniform myhalf4 ReflectColor;\n"
822 "uniform myhalf ReflectFactor;\n"
823 "uniform myhalf ReflectOffset;\n"
825 "//# ifdef MODE_REFRACTION\n"
826 "//uniform vec4 DistortScaleRefractReflect;\n"
827 "//uniform vec4 ScreenScaleRefractReflect;\n"
828 "//uniform vec4 ScreenCenterRefractReflect;\n"
829 "//uniform myhalf4 RefractColor;\n"
830 "//# ifdef USEREFLECTION\n"
831 "//uniform myhalf4 ReflectColor;\n"
834 "//# ifdef USEREFLECTION\n"
835 "//uniform vec4 DistortScaleRefractReflect;\n"
836 "//uniform vec4 ScreenScaleRefractReflect;\n"
837 "//uniform vec4 ScreenCenterRefractReflect;\n"
838 "//uniform myhalf4 ReflectColor;\n"
843 "uniform myhalf3 GlowColor;\n"
844 "uniform myhalf SceneBrightness;\n"
846 "uniform float OffsetMapping_Scale;\n"
847 "uniform float OffsetMapping_Bias;\n"
848 "uniform float FogRangeRecip;\n"
850 "uniform myhalf AmbientScale;\n"
851 "uniform myhalf DiffuseScale;\n"
852 "uniform myhalf SpecularScale;\n"
853 "uniform myhalf SpecularPower;\n"
855 "#ifdef USEOFFSETMAPPING\n"
856 "vec2 OffsetMapping(vec2 TexCoord)\n"
858 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
859 " // 14 sample relief mapping: linear search and then binary search\n"
860 " // this basically steps forward a small amount repeatedly until it finds\n"
861 " // itself inside solid, then jitters forward and back using decreasing\n"
862 " // amounts to find the impact\n"
863 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
864 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
865 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
866 " vec3 RT = vec3(TexCoord, 1);\n"
867 " OffsetVector *= 0.1;\n"
868 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
869 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
870 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
871 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
872 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
878 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
879 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
880 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
881 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
884 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
885 " // this basically moves forward the full distance, and then backs up based\n"
886 " // on height of samples\n"
887 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
888 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
889 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
890 " TexCoord += OffsetVector;\n"
891 " OffsetVector *= 0.333;\n"
892 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
893 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
894 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
895 " return TexCoord;\n"
898 "#endif // USEOFFSETMAPPING\n"
900 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
901 "uniform vec2 ShadowMap_TextureScale;\n"
902 "uniform vec4 ShadowMap_Parameters;\n"
905 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
906 "vec3 GetShadowMapTC2D(vec3 dir)\n"
908 " vec3 adir = abs(dir);\n"
909 "# ifndef USESHADOWMAPVSDCT\n"
913 " if (adir.x > adir.y)\n"
915 " if (adir.x > adir.z) // X\n"
919 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
925 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
930 " if (adir.y > adir.z) // Y\n"
934 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
940 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
944 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
945 " stc.xy += offset * ShadowMap_Parameters.y;\n"
946 " stc.z += ShadowMap_Parameters.z;\n"
947 "# if showshadowmap\n"
948 " stc.xy *= ShadowMap_TextureScale;\n"
952 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
953 " float ma = max(max(adir.x, adir.y), adir.z);\n"
954 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
955 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
956 " stc.z += ShadowMap_Parameters.z;\n"
957 "# if showshadowmap\n"
958 " stc.xy *= ShadowMap_TextureScale;\n"
963 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
965 "#ifdef USESHADOWMAPCUBE\n"
966 "vec4 GetShadowMapTCCube(vec3 dir)\n"
968 " vec3 adir = abs(dir);\n"
969 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
973 "#if !showshadowmap\n"
974 "# ifdef USESHADOWMAPRECT\n"
975 "float ShadowMapCompare(vec3 dir)\n"
977 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
979 "# ifdef USESHADOWSAMPLER\n"
981 "# ifdef USESHADOWMAPPCF\n"
982 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
983 " 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"
985 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
990 "# ifdef USESHADOWMAPPCF\n"
991 "# if USESHADOWMAPPCF > 1\n"
992 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
993 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
994 " 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"
995 " 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"
996 " 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"
997 " 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"
998 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
999 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1001 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1002 " vec2 offset = fract(shadowmaptc.xy);\n"
1003 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1004 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1005 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1006 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1007 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1010 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1018 "# ifdef USESHADOWMAP2D\n"
1019 "float ShadowMapCompare(vec3 dir)\n"
1021 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1024 "# ifdef USESHADOWSAMPLER\n"
1025 "# ifdef USESHADOWMAPPCF\n"
1026 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1027 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1028 " 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"
1030 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1033 "# ifdef USESHADOWMAPPCF\n"
1034 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1035 "# ifdef GL_ARB_texture_gather\n"
1036 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1038 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1040 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1041 " center *= ShadowMap_TextureScale;\n"
1042 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1043 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1044 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1045 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1046 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1047 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1048 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1050 "# ifdef GL_EXT_gpu_shader4\n"
1051 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1053 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1055 "# if USESHADOWMAPPCF > 1\n"
1056 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1057 " center *= ShadowMap_TextureScale;\n"
1058 " 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"
1059 " 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"
1060 " 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"
1061 " 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"
1062 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1063 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1065 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1066 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1067 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1068 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1069 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1070 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1074 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1081 "# ifdef USESHADOWMAPCUBE\n"
1082 "float ShadowMapCompare(vec3 dir)\n"
1084 " // apply depth texture cubemap as light filter\n"
1085 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1087 "# ifdef USESHADOWSAMPLER\n"
1088 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1090 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1097 "#ifdef MODE_WATER\n"
1102 "#ifdef USEOFFSETMAPPING\n"
1103 " // apply offsetmapping\n"
1104 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1105 "#define TexCoord TexCoordOffset\n"
1108 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1109 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1110 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1111 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1112 " // FIXME temporary hack to detect the case that the reflection\n"
1113 " // gets blackened at edges due to leaving the area that contains actual\n"
1115 " // Remove this 'ack once we have a better way to stop this thing from\n"
1117 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1118 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1119 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1120 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1121 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1122 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1123 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1124 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1125 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1126 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1127 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1128 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1131 "#else // !MODE_WATER\n"
1132 "#ifdef MODE_REFRACTION\n"
1134 "// refraction pass\n"
1137 "#ifdef USEOFFSETMAPPING\n"
1138 " // apply offsetmapping\n"
1139 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1140 "#define TexCoord TexCoordOffset\n"
1143 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1144 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1145 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1146 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1147 " // FIXME temporary hack to detect the case that the reflection\n"
1148 " // gets blackened at edges due to leaving the area that contains actual\n"
1150 " // Remove this 'ack once we have a better way to stop this thing from\n"
1152 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1153 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1154 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1155 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1156 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1157 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1160 "#else // !MODE_REFRACTION\n"
1163 "#ifdef USEOFFSETMAPPING\n"
1164 " // apply offsetmapping\n"
1165 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1166 "#define TexCoord TexCoordOffset\n"
1169 " // combine the diffuse textures (base, pants, shirt)\n"
1170 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1171 "#ifdef USECOLORMAPPING\n"
1172 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1174 "#ifdef USEVERTEXTEXTUREBLEND\n"
1175 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1176 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1177 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1178 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1180 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1183 "#ifdef USEDIFFUSE\n"
1184 " // get the surface normal and the gloss color\n"
1185 "# ifdef USEVERTEXTEXTUREBLEND\n"
1186 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1187 "# ifdef USESPECULAR\n"
1188 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1191 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1192 "# ifdef USESPECULAR\n"
1193 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1200 "#ifdef MODE_LIGHTSOURCE\n"
1201 " // light source\n"
1203 " // calculate surface normal, light normal, and specular normal\n"
1204 " // compute color intensity for the two textures (colormap and glossmap)\n"
1205 " // scale by light color and attenuation as efficiently as possible\n"
1206 " // (do as much scalar math as possible rather than vector math)\n"
1207 "# ifdef USEDIFFUSE\n"
1208 " // get the light normal\n"
1209 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1211 "# ifdef USESPECULAR\n"
1212 "# ifndef USEEXACTSPECULARMATH\n"
1213 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1216 " // calculate directional shading\n"
1217 "# ifdef USEEXACTSPECULARMATH\n"
1218 " 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"
1220 " 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"
1223 "# ifdef USEDIFFUSE\n"
1224 " // calculate directional shading\n"
1225 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1227 " // calculate directionless shading\n"
1228 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1232 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1233 "#if !showshadowmap\n"
1234 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1238 "# ifdef USECUBEFILTER\n"
1239 " // apply light cubemap filter\n"
1240 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1241 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1243 "#endif // MODE_LIGHTSOURCE\n"
1248 "#ifdef MODE_LIGHTDIRECTION\n"
1249 " // directional model lighting\n"
1250 "# ifdef USEDIFFUSE\n"
1251 " // get the light normal\n"
1252 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1254 "# ifdef USESPECULAR\n"
1255 " // calculate directional shading\n"
1256 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1257 "# ifdef USEEXACTSPECULARMATH\n"
1258 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1260 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1261 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1264 "# ifdef USEDIFFUSE\n"
1266 " // calculate directional shading\n"
1267 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1269 " color.rgb *= AmbientColor;\n"
1272 "#endif // MODE_LIGHTDIRECTION\n"
1277 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1278 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1280 " // get the light normal\n"
1281 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1282 " myhalf3 diffusenormal;\n"
1283 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1284 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1285 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1286 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1287 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1288 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1289 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1290 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1291 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1292 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1293 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1294 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1295 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1296 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1297 "# ifdef USESPECULAR\n"
1298 "# ifdef USEEXACTSPECULARMATH\n"
1299 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1301 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1302 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1306 " // apply lightmap color\n"
1307 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1308 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1313 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1314 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1316 " // get the light normal\n"
1317 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1318 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1319 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1320 "# ifdef USESPECULAR\n"
1321 "# ifdef USEEXACTSPECULARMATH\n"
1322 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1324 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1325 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1329 " // apply lightmap color\n"
1330 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1331 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1336 "#ifdef MODE_LIGHTMAP\n"
1337 " // apply lightmap color\n"
1338 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1339 "#endif // MODE_LIGHTMAP\n"
1344 "#ifdef MODE_VERTEXCOLOR\n"
1345 " // apply lightmap color\n"
1346 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1347 "#endif // MODE_VERTEXCOLOR\n"
1352 "#ifdef MODE_FLATCOLOR\n"
1353 "#endif // MODE_FLATCOLOR\n"
1361 " color *= TintColor;\n"
1364 "#ifdef USEVERTEXTEXTUREBLEND\n"
1365 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1367 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1371 " color.rgb *= SceneBrightness;\n"
1373 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1375 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1378 " // 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"
1379 "#ifdef USEREFLECTION\n"
1380 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1381 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1382 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1383 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1384 " // FIXME temporary hack to detect the case that the reflection\n"
1385 " // gets blackened at edges due to leaving the area that contains actual\n"
1387 " // Remove this 'ack once we have a better way to stop this thing from\n"
1389 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1390 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1391 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1392 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1393 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1394 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1397 " gl_FragColor = vec4(color);\n"
1399 "#if showshadowmap\n"
1400 "# ifdef USESHADOWMAPRECT\n"
1401 "# ifdef USESHADOWSAMPLER\n"
1402 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1404 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1407 "# ifdef USESHADOWMAP2D\n"
1408 "# ifdef USESHADOWSAMPLER\n"
1409 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1411 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1415 "# ifdef USESHADOWMAPCUBE\n"
1416 "# ifdef USESHADOWSAMPLER\n"
1417 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1419 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1424 "#endif // !MODE_REFRACTION\n"
1425 "#endif // !MODE_WATER\n"
1427 "#endif // FRAGMENT_SHADER\n"
1429 "#endif // !MODE_GENERIC\n"
1430 "#endif // !MODE_POSTPROCESS\n"
1431 "#endif // !MODE_SHOWDEPTH\n"
1432 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1435 typedef struct shaderpermutationinfo_s
1437 const char *pretext;
1440 shaderpermutationinfo_t;
1442 typedef struct shadermodeinfo_s
1444 const char *vertexfilename;
1445 const char *geometryfilename;
1446 const char *fragmentfilename;
1447 const char *pretext;
1452 typedef enum shaderpermutation_e
1454 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1455 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1456 SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
1457 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1458 SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
1459 SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
1460 SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
1461 SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
1462 SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
1463 SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
1464 SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
1465 SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
1466 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1467 SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1468 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
1469 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1470 SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
1471 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
1472 SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
1473 SHADERPERMUTATION_SHADOWMAPPCF = 1<<14, ///< (lightsource) use percentage closer filtering on shadowmap test results
1474 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<15, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1475 SHADERPERMUTATION_SHADOWSAMPLER = 1<<16, ///< (lightsource) use hardware shadowmap test
1476 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<17, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1477 SHADERPERMUTATION_LIMIT = 1<<18, ///< size of permutations array
1478 SHADERPERMUTATION_COUNT = 18 ///< size of shaderpermutationinfo array
1480 shaderpermutation_t;
1482 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1483 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1485 {"#define USEDIFFUSE\n", " diffuse"},
1486 {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
1487 {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
1488 {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
1489 {"#define USECUBEFILTER\n", " cubefilter"},
1490 {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
1491 {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
1492 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1493 {"#define USEREFLECTION\n", " reflection"},
1494 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1495 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1496 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1497 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1498 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1499 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1500 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1501 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1502 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1505 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1506 typedef enum shadermode_e
1508 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1509 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1510 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1511 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1512 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1513 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1514 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1515 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1516 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1517 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1518 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1519 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1520 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1525 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1526 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1528 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1529 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1530 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1531 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1532 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1533 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1534 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1535 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1536 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1537 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1538 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1539 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1540 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1543 struct r_glsl_permutation_s;
1544 typedef struct r_glsl_permutation_s
1546 /// hash lookup data
1547 struct r_glsl_permutation_s *hashnext;
1549 unsigned int permutation;
1551 /// indicates if we have tried compiling this permutation already
1553 /// 0 if compilation failed
1555 /// locations of detected uniforms in program object, or -1 if not found
1556 int loc_Texture_First;
1557 int loc_Texture_Second;
1558 int loc_Texture_GammaRamps;
1559 int loc_Texture_Normal;
1560 int loc_Texture_Color;
1561 int loc_Texture_Gloss;
1562 int loc_Texture_Glow;
1563 int loc_Texture_SecondaryNormal;
1564 int loc_Texture_SecondaryColor;
1565 int loc_Texture_SecondaryGloss;
1566 int loc_Texture_SecondaryGlow;
1567 int loc_Texture_Pants;
1568 int loc_Texture_Shirt;
1569 int loc_Texture_FogMask;
1570 int loc_Texture_Lightmap;
1571 int loc_Texture_Deluxemap;
1572 int loc_Texture_Attenuation;
1573 int loc_Texture_Cube;
1574 int loc_Texture_Refraction;
1575 int loc_Texture_Reflection;
1576 int loc_Texture_ShadowMapRect;
1577 int loc_Texture_ShadowMapCube;
1578 int loc_Texture_ShadowMap2D;
1579 int loc_Texture_CubeProjection;
1581 int loc_LightPosition;
1582 int loc_EyePosition;
1583 int loc_Color_Pants;
1584 int loc_Color_Shirt;
1585 int loc_FogRangeRecip;
1586 int loc_AmbientScale;
1587 int loc_DiffuseScale;
1588 int loc_SpecularScale;
1589 int loc_SpecularPower;
1591 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1592 int loc_OffsetMapping_Scale;
1594 int loc_AmbientColor;
1595 int loc_DiffuseColor;
1596 int loc_SpecularColor;
1598 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1599 int loc_GammaCoeff; ///< 1 / gamma
1600 int loc_DistortScaleRefractReflect;
1601 int loc_ScreenScaleRefractReflect;
1602 int loc_ScreenCenterRefractReflect;
1603 int loc_RefractColor;
1604 int loc_ReflectColor;
1605 int loc_ReflectFactor;
1606 int loc_ReflectOffset;
1614 int loc_ShadowMap_TextureScale;
1615 int loc_ShadowMap_Parameters;
1617 r_glsl_permutation_t;
1619 #define SHADERPERMUTATION_HASHSIZE 4096
1621 /// information about each possible shader permutation
1622 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1623 /// currently selected permutation
1624 r_glsl_permutation_t *r_glsl_permutation;
1625 /// storage for permutations linked in the hash table
1626 memexpandablearray_t r_glsl_permutationarray;
1628 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1630 //unsigned int hashdepth = 0;
1631 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1632 r_glsl_permutation_t *p;
1633 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1635 if (p->mode == mode && p->permutation == permutation)
1637 //if (hashdepth > 10)
1638 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1643 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1645 p->permutation = permutation;
1646 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1647 r_glsl_permutationhash[mode][hashindex] = p;
1648 //if (hashdepth > 10)
1649 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1653 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1656 if (!filename || !filename[0])
1658 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1661 if (printfromdisknotice)
1662 Con_DPrint("from disk... ");
1663 return shaderstring;
1665 else if (!strcmp(filename, "glsl/default.glsl"))
1667 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1668 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1670 return shaderstring;
1673 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1676 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1677 int vertstrings_count = 0;
1678 int geomstrings_count = 0;
1679 int fragstrings_count = 0;
1680 char *vertexstring, *geometrystring, *fragmentstring;
1681 const char *vertstrings_list[32+3];
1682 const char *geomstrings_list[32+3];
1683 const char *fragstrings_list[32+3];
1684 char permutationname[256];
1691 permutationname[0] = 0;
1692 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1693 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1694 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1696 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1698 // the first pretext is which type of shader to compile as
1699 // (later these will all be bound together as a program object)
1700 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1701 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1702 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1704 // the second pretext is the mode (for example a light source)
1705 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1706 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1707 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1708 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1710 // now add all the permutation pretexts
1711 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1713 if (permutation & (1<<i))
1715 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1716 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1717 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1718 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1722 // keep line numbers correct
1723 vertstrings_list[vertstrings_count++] = "\n";
1724 geomstrings_list[geomstrings_count++] = "\n";
1725 fragstrings_list[fragstrings_count++] = "\n";
1729 // now append the shader text itself
1730 vertstrings_list[vertstrings_count++] = vertexstring;
1731 geomstrings_list[geomstrings_count++] = geometrystring;
1732 fragstrings_list[fragstrings_count++] = fragmentstring;
1734 // if any sources were NULL, clear the respective list
1736 vertstrings_count = 0;
1737 if (!geometrystring)
1738 geomstrings_count = 0;
1739 if (!fragmentstring)
1740 fragstrings_count = 0;
1742 // compile the shader program
1743 if (vertstrings_count + geomstrings_count + fragstrings_count)
1744 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1748 qglUseProgramObjectARB(p->program);CHECKGLERROR
1749 // look up all the uniform variable names we care about, so we don't
1750 // have to look them up every time we set them
1751 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1752 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1753 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1754 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1755 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1756 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1757 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1758 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1759 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1760 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1761 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1762 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1763 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1764 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1765 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1766 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1767 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1768 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1769 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1770 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1771 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1772 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1773 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1774 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1775 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1776 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1777 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1778 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1779 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1780 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1781 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1782 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1783 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1784 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1785 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1786 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1787 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1788 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1789 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1790 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1791 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1792 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1793 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1794 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1795 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1796 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1797 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1798 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1799 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1800 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1801 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1802 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1803 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1804 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1805 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1806 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1807 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1808 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1809 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1810 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1811 // initialize the samplers to refer to the texture units we use
1812 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1813 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1814 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1815 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1816 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1817 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1818 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1819 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1820 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1821 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1822 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1823 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1824 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1825 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1826 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1827 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1828 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1829 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1830 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1831 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1832 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1833 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1834 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1835 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1837 if (developer.integer)
1838 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1841 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1845 Mem_Free(vertexstring);
1847 Mem_Free(geometrystring);
1849 Mem_Free(fragmentstring);
1852 void R_GLSL_Restart_f(void)
1854 unsigned int i, limit;
1855 r_glsl_permutation_t *p;
1856 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1857 for (i = 0;i < limit;i++)
1859 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1861 GL_Backend_FreeProgram(p->program);
1862 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1865 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1868 void R_GLSL_DumpShader_f(void)
1872 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1875 Con_Printf("failed to write to glsl/default.glsl\n");
1879 FS_Print(file, "/* The engine may define the following macros:\n");
1880 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1881 for (i = 0;i < SHADERMODE_COUNT;i++)
1882 FS_Print(file, shadermodeinfo[i].pretext);
1883 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1884 FS_Print(file, shaderpermutationinfo[i].pretext);
1885 FS_Print(file, "*/\n");
1886 FS_Print(file, builtinshaderstring);
1889 Con_Printf("glsl/default.glsl written\n");
1892 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1894 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1895 if (r_glsl_permutation != perm)
1897 r_glsl_permutation = perm;
1898 if (!r_glsl_permutation->program)
1900 if (!r_glsl_permutation->compiled)
1901 R_GLSL_CompilePermutation(perm, mode, permutation);
1902 if (!r_glsl_permutation->program)
1904 // remove features until we find a valid permutation
1906 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1908 // reduce i more quickly whenever it would not remove any bits
1909 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1910 if (!(permutation & j))
1913 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1914 if (!r_glsl_permutation->compiled)
1915 R_GLSL_CompilePermutation(perm, mode, permutation);
1916 if (r_glsl_permutation->program)
1919 if (i >= SHADERPERMUTATION_COUNT)
1921 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");
1922 Cvar_SetValueQuick(&r_glsl, 0);
1923 R_GLSL_Restart_f(); // unload shaders
1924 return; // no bit left to clear
1929 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1933 void R_SetupGenericShader(qboolean usetexture)
1935 if (gl_support_fragment_shader)
1937 if (r_glsl.integer && r_glsl_usegeneric.integer)
1938 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1939 else if (r_glsl_permutation)
1941 r_glsl_permutation = NULL;
1942 qglUseProgramObjectARB(0);CHECKGLERROR
1947 void R_SetupGenericTwoTextureShader(int texturemode)
1949 if (gl_support_fragment_shader)
1951 if (r_glsl.integer && r_glsl_usegeneric.integer)
1952 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))));
1953 else if (r_glsl_permutation)
1955 r_glsl_permutation = NULL;
1956 qglUseProgramObjectARB(0);CHECKGLERROR
1959 if (!r_glsl_permutation)
1961 if (texturemode == GL_DECAL && gl_combine.integer)
1962 texturemode = GL_INTERPOLATE_ARB;
1963 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1967 void R_SetupDepthOrShadowShader(void)
1969 if (gl_support_fragment_shader)
1971 if (r_glsl.integer && r_glsl_usegeneric.integer)
1972 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1973 else if (r_glsl_permutation)
1975 r_glsl_permutation = NULL;
1976 qglUseProgramObjectARB(0);CHECKGLERROR
1981 void R_SetupShowDepthShader(void)
1983 if (gl_support_fragment_shader)
1985 if (r_glsl.integer && r_glsl_usegeneric.integer)
1986 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
1987 else if (r_glsl_permutation)
1989 r_glsl_permutation = NULL;
1990 qglUseProgramObjectARB(0);CHECKGLERROR
1995 extern rtexture_t *r_shadow_attenuationgradienttexture;
1996 extern rtexture_t *r_shadow_attenuation2dtexture;
1997 extern rtexture_t *r_shadow_attenuation3dtexture;
1998 extern qboolean r_shadow_usingshadowmaprect;
1999 extern qboolean r_shadow_usingshadowmapcube;
2000 extern qboolean r_shadow_usingshadowmap2d;
2001 extern float r_shadow_shadowmap_texturescale[2];
2002 extern float r_shadow_shadowmap_parameters[4];
2003 extern qboolean r_shadow_shadowmapvsdct;
2004 extern qboolean r_shadow_shadowmapsampler;
2005 extern int r_shadow_shadowmappcf;
2006 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2008 // select a permutation of the lighting shader appropriate to this
2009 // combination of texture, entity, light source, and fogging, only use the
2010 // minimum features necessary to avoid wasting rendering time in the
2011 // fragment shader on features that are not being used
2012 unsigned int permutation = 0;
2013 unsigned int mode = 0;
2014 // TODO: implement geometry-shader based shadow volumes someday
2015 if (r_glsl_offsetmapping.integer)
2017 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2018 if (r_glsl_offsetmapping_reliefmapping.integer)
2019 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2021 if (rsurfacepass == RSURFPASS_BACKGROUND)
2023 // distorted background
2024 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2025 mode = SHADERMODE_WATER;
2027 mode = SHADERMODE_REFRACTION;
2029 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2032 mode = SHADERMODE_LIGHTSOURCE;
2033 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2034 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2035 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2036 permutation |= SHADERPERMUTATION_CUBEFILTER;
2037 if (diffusescale > 0)
2038 permutation |= SHADERPERMUTATION_DIFFUSE;
2039 if (specularscale > 0)
2040 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2041 if (r_refdef.fogenabled)
2042 permutation |= SHADERPERMUTATION_FOG;
2043 if (rsurface.texture->colormapping)
2044 permutation |= SHADERPERMUTATION_COLORMAPPING;
2045 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2047 if (r_shadow_usingshadowmaprect)
2048 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2049 if (r_shadow_usingshadowmap2d)
2050 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2051 if (r_shadow_usingshadowmapcube)
2052 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2053 else if(r_shadow_shadowmapvsdct)
2054 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2056 if (r_shadow_shadowmapsampler)
2057 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2058 if (r_shadow_shadowmappcf > 1)
2059 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2060 else if (r_shadow_shadowmappcf)
2061 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2064 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2066 // unshaded geometry (fullbright or ambient model lighting)
2067 mode = SHADERMODE_FLATCOLOR;
2068 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2069 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2070 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2071 permutation |= SHADERPERMUTATION_GLOW;
2072 if (r_refdef.fogenabled)
2073 permutation |= SHADERPERMUTATION_FOG;
2074 if (rsurface.texture->colormapping)
2075 permutation |= SHADERPERMUTATION_COLORMAPPING;
2076 if (r_glsl_offsetmapping.integer)
2078 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2079 if (r_glsl_offsetmapping_reliefmapping.integer)
2080 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2082 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2083 permutation |= SHADERPERMUTATION_REFLECTION;
2085 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2087 // directional model lighting
2088 mode = SHADERMODE_LIGHTDIRECTION;
2089 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2090 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2091 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2092 permutation |= SHADERPERMUTATION_GLOW;
2093 permutation |= SHADERPERMUTATION_DIFFUSE;
2094 if (specularscale > 0)
2095 permutation |= SHADERPERMUTATION_SPECULAR;
2096 if (r_refdef.fogenabled)
2097 permutation |= SHADERPERMUTATION_FOG;
2098 if (rsurface.texture->colormapping)
2099 permutation |= SHADERPERMUTATION_COLORMAPPING;
2100 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2101 permutation |= SHADERPERMUTATION_REFLECTION;
2103 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2105 // ambient model lighting
2106 mode = SHADERMODE_LIGHTDIRECTION;
2107 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2108 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2109 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2110 permutation |= SHADERPERMUTATION_GLOW;
2111 if (r_refdef.fogenabled)
2112 permutation |= SHADERPERMUTATION_FOG;
2113 if (rsurface.texture->colormapping)
2114 permutation |= SHADERPERMUTATION_COLORMAPPING;
2115 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2116 permutation |= SHADERPERMUTATION_REFLECTION;
2121 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2123 // deluxemapping (light direction texture)
2124 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2125 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2127 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2128 permutation |= SHADERPERMUTATION_DIFFUSE;
2129 if (specularscale > 0)
2130 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2132 else if (r_glsl_deluxemapping.integer >= 2)
2134 // fake deluxemapping (uniform light direction in tangentspace)
2135 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2136 permutation |= SHADERPERMUTATION_DIFFUSE;
2137 if (specularscale > 0)
2138 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2140 else if (rsurface.uselightmaptexture)
2142 // ordinary lightmapping (q1bsp, q3bsp)
2143 mode = SHADERMODE_LIGHTMAP;
2147 // ordinary vertex coloring (q3bsp)
2148 mode = SHADERMODE_VERTEXCOLOR;
2150 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2151 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2152 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2153 permutation |= SHADERPERMUTATION_GLOW;
2154 if (r_refdef.fogenabled)
2155 permutation |= SHADERPERMUTATION_FOG;
2156 if (rsurface.texture->colormapping)
2157 permutation |= SHADERPERMUTATION_COLORMAPPING;
2158 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2159 permutation |= SHADERPERMUTATION_REFLECTION;
2161 if(permutation & SHADERPERMUTATION_SPECULAR)
2162 if(r_shadow_glossexact.integer)
2163 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2164 R_SetupShader_SetPermutation(mode, permutation);
2165 if (mode == SHADERMODE_LIGHTSOURCE)
2167 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2168 if (permutation & SHADERPERMUTATION_DIFFUSE)
2170 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2171 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2172 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2173 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2177 // ambient only is simpler
2178 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]);
2179 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2180 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2181 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2183 // additive passes are only darkened by fog, not tinted
2184 if (r_glsl_permutation->loc_FogColor >= 0)
2185 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2186 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]);
2187 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]);
2191 if (mode == SHADERMODE_LIGHTDIRECTION)
2193 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);
2194 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);
2195 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);
2196 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]);
2200 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2201 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2202 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2204 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]);
2205 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);
2206 // additive passes are only darkened by fog, not tinted
2207 if (r_glsl_permutation->loc_FogColor >= 0)
2209 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2210 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2212 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2214 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);
2215 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]);
2216 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]);
2217 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2218 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2219 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2220 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2222 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2223 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2224 if (r_glsl_permutation->loc_Color_Pants >= 0)
2226 if (rsurface.texture->currentskinframe->pants)
2227 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2229 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2231 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2233 if (rsurface.texture->currentskinframe->shirt)
2234 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2236 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2238 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
2239 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2241 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2245 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2247 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2251 #define SKINFRAME_HASH 1024
2255 int loadsequence; // incremented each level change
2256 memexpandablearray_t array;
2257 skinframe_t *hash[SKINFRAME_HASH];
2260 r_skinframe_t r_skinframe;
2262 void R_SkinFrame_PrepareForPurge(void)
2264 r_skinframe.loadsequence++;
2265 // wrap it without hitting zero
2266 if (r_skinframe.loadsequence >= 200)
2267 r_skinframe.loadsequence = 1;
2270 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2274 // mark the skinframe as used for the purging code
2275 skinframe->loadsequence = r_skinframe.loadsequence;
2278 void R_SkinFrame_Purge(void)
2282 for (i = 0;i < SKINFRAME_HASH;i++)
2284 for (s = r_skinframe.hash[i];s;s = s->next)
2286 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2288 if (s->merged == s->base)
2290 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2291 R_PurgeTexture(s->stain );s->stain = NULL;
2292 R_PurgeTexture(s->merged);s->merged = NULL;
2293 R_PurgeTexture(s->base );s->base = NULL;
2294 R_PurgeTexture(s->pants );s->pants = NULL;
2295 R_PurgeTexture(s->shirt );s->shirt = NULL;
2296 R_PurgeTexture(s->nmap );s->nmap = NULL;
2297 R_PurgeTexture(s->gloss );s->gloss = NULL;
2298 R_PurgeTexture(s->glow );s->glow = NULL;
2299 R_PurgeTexture(s->fog );s->fog = NULL;
2300 s->loadsequence = 0;
2306 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2308 char basename[MAX_QPATH];
2310 Image_StripImageExtension(name, basename, sizeof(basename));
2312 if( last == NULL ) {
2314 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2315 item = r_skinframe.hash[hashindex];
2320 // linearly search through the hash bucket
2321 for( ; item ; item = item->next ) {
2322 if( !strcmp( item->basename, basename ) ) {
2329 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2333 char basename[MAX_QPATH];
2335 Image_StripImageExtension(name, basename, sizeof(basename));
2337 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2338 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2339 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2343 rtexture_t *dyntexture;
2344 // check whether its a dynamic texture
2345 dyntexture = CL_GetDynTexture( basename );
2346 if (!add && !dyntexture)
2348 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2349 memset(item, 0, sizeof(*item));
2350 strlcpy(item->basename, basename, sizeof(item->basename));
2351 item->base = dyntexture; // either NULL or dyntexture handle
2352 item->textureflags = textureflags;
2353 item->comparewidth = comparewidth;
2354 item->compareheight = compareheight;
2355 item->comparecrc = comparecrc;
2356 item->next = r_skinframe.hash[hashindex];
2357 r_skinframe.hash[hashindex] = item;
2359 else if( item->base == NULL )
2361 rtexture_t *dyntexture;
2362 // check whether its a dynamic texture
2363 // 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]
2364 dyntexture = CL_GetDynTexture( basename );
2365 item->base = dyntexture; // either NULL or dyntexture handle
2368 R_SkinFrame_MarkUsed(item);
2372 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2374 unsigned long long avgcolor[5], wsum; \
2382 for(pix = 0; pix < cnt; ++pix) \
2385 for(comp = 0; comp < 3; ++comp) \
2387 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2390 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2392 for(comp = 0; comp < 3; ++comp) \
2393 avgcolor[comp] += getpixel * w; \
2396 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2397 avgcolor[4] += getpixel; \
2399 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2401 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2402 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2403 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2404 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2407 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2409 // FIXME: it should be possible to disable loading various layers using
2410 // cvars, to prevent wasted loading time and memory usage if the user does
2412 qboolean loadnormalmap = true;
2413 qboolean loadgloss = true;
2414 qboolean loadpantsandshirt = true;
2415 qboolean loadglow = true;
2417 unsigned char *pixels;
2418 unsigned char *bumppixels;
2419 unsigned char *basepixels = NULL;
2420 int basepixels_width;
2421 int basepixels_height;
2422 skinframe_t *skinframe;
2427 if (cls.state == ca_dedicated)
2430 // return an existing skinframe if already loaded
2431 // if loading of the first image fails, don't make a new skinframe as it
2432 // would cause all future lookups of this to be missing
2433 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2434 if (skinframe && skinframe->base)
2437 basepixels = loadimagepixelsbgra(name, complain, true);
2438 if (basepixels == NULL)
2441 if (developer_loading.integer)
2442 Con_Printf("loading skin \"%s\"\n", name);
2444 // we've got some pixels to store, so really allocate this new texture now
2446 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2447 skinframe->stain = NULL;
2448 skinframe->merged = NULL;
2449 skinframe->base = r_texture_notexture;
2450 skinframe->pants = NULL;
2451 skinframe->shirt = NULL;
2452 skinframe->nmap = r_texture_blanknormalmap;
2453 skinframe->gloss = NULL;
2454 skinframe->glow = NULL;
2455 skinframe->fog = NULL;
2457 basepixels_width = image_width;
2458 basepixels_height = image_height;
2459 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);
2461 if (textureflags & TEXF_ALPHA)
2463 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2464 if (basepixels[j] < 255)
2466 if (j < basepixels_width * basepixels_height * 4)
2468 // has transparent pixels
2471 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2472 for (j = 0;j < image_width * image_height * 4;j += 4)
2477 pixels[j+3] = basepixels[j+3];
2479 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);
2484 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2485 //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]);
2487 // _norm is the name used by tenebrae and has been adopted as standard
2490 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2492 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);
2496 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2498 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2499 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2500 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2502 Mem_Free(bumppixels);
2504 else if (r_shadow_bumpscale_basetexture.value > 0)
2506 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2507 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2508 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);
2512 // _luma is supported for tenebrae compatibility
2513 // (I think it's a very stupid name, but oh well)
2514 // _glow is the preferred name
2515 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;}
2516 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;}
2517 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;}
2518 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;}
2521 Mem_Free(basepixels);
2526 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2528 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, NULL);
2531 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)
2536 for (i = 0;i < width*height;i++)
2537 if (((unsigned char *)&palette[in[i]])[3] > 0)
2539 if (i == width*height)
2542 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2545 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2546 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2549 unsigned char *temp1, *temp2;
2550 skinframe_t *skinframe;
2552 if (cls.state == ca_dedicated)
2555 // if already loaded just return it, otherwise make a new skinframe
2556 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2557 if (skinframe && skinframe->base)
2560 skinframe->stain = NULL;
2561 skinframe->merged = NULL;
2562 skinframe->base = r_texture_notexture;
2563 skinframe->pants = NULL;
2564 skinframe->shirt = NULL;
2565 skinframe->nmap = r_texture_blanknormalmap;
2566 skinframe->gloss = NULL;
2567 skinframe->glow = NULL;
2568 skinframe->fog = NULL;
2570 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2574 if (developer_loading.integer)
2575 Con_Printf("loading 32bit skin \"%s\"\n", name);
2577 if (r_shadow_bumpscale_basetexture.value > 0)
2579 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2580 temp2 = temp1 + width * height * 4;
2581 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2582 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2585 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2586 if (textureflags & TEXF_ALPHA)
2588 for (i = 3;i < width * height * 4;i += 4)
2589 if (skindata[i] < 255)
2591 if (i < width * height * 4)
2593 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2594 memcpy(fogpixels, skindata, width * height * 4);
2595 for (i = 0;i < width * height * 4;i += 4)
2596 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2597 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2598 Mem_Free(fogpixels);
2602 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2603 //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]);
2608 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2611 unsigned char *temp1, *temp2;
2612 unsigned int *palette;
2613 skinframe_t *skinframe;
2615 if (cls.state == ca_dedicated)
2618 // if already loaded just return it, otherwise make a new skinframe
2619 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2620 if (skinframe && skinframe->base)
2623 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2625 skinframe->stain = NULL;
2626 skinframe->merged = NULL;
2627 skinframe->base = r_texture_notexture;
2628 skinframe->pants = NULL;
2629 skinframe->shirt = NULL;
2630 skinframe->nmap = r_texture_blanknormalmap;
2631 skinframe->gloss = NULL;
2632 skinframe->glow = NULL;
2633 skinframe->fog = NULL;
2635 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2639 if (developer_loading.integer)
2640 Con_Printf("loading quake skin \"%s\"\n", name);
2642 if (r_shadow_bumpscale_basetexture.value > 0)
2644 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2645 temp2 = temp1 + width * height * 4;
2646 // use either a custom palette or the quake palette
2647 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2648 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2649 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2652 // use either a custom palette, or the quake palette
2653 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2654 if (loadglowtexture)
2655 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2656 if (loadpantsandshirt)
2658 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2659 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2661 if (skinframe->pants || skinframe->shirt)
2662 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
2663 if (textureflags & TEXF_ALPHA)
2665 for (i = 0;i < width * height;i++)
2666 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2668 if (i < width * height)
2669 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2672 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2673 //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]);
2678 skinframe_t *R_SkinFrame_LoadMissing(void)
2680 skinframe_t *skinframe;
2682 if (cls.state == ca_dedicated)
2685 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2686 skinframe->stain = NULL;
2687 skinframe->merged = NULL;
2688 skinframe->base = r_texture_notexture;
2689 skinframe->pants = NULL;
2690 skinframe->shirt = NULL;
2691 skinframe->nmap = r_texture_blanknormalmap;
2692 skinframe->gloss = NULL;
2693 skinframe->glow = NULL;
2694 skinframe->fog = NULL;
2696 skinframe->avgcolor[0] = rand() / RAND_MAX;
2697 skinframe->avgcolor[1] = rand() / RAND_MAX;
2698 skinframe->avgcolor[2] = rand() / RAND_MAX;
2699 skinframe->avgcolor[3] = 1;
2704 void gl_main_start(void)
2708 memset(r_queries, 0, sizeof(r_queries));
2710 r_qwskincache = NULL;
2711 r_qwskincache_size = 0;
2713 // set up r_skinframe loading system for textures
2714 memset(&r_skinframe, 0, sizeof(r_skinframe));
2715 r_skinframe.loadsequence = 1;
2716 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2718 r_main_texturepool = R_AllocTexturePool();
2719 R_BuildBlankTextures();
2721 if (gl_texturecubemap)
2724 R_BuildNormalizationCube();
2726 r_texture_fogattenuation = NULL;
2727 r_texture_gammaramps = NULL;
2728 //r_texture_fogintensity = NULL;
2729 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2730 memset(&r_waterstate, 0, sizeof(r_waterstate));
2731 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2732 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2733 memset(&r_svbsp, 0, sizeof (r_svbsp));
2735 r_refdef.fogmasktable_density = 0;
2738 extern rtexture_t *loadingscreentexture;
2739 void gl_main_shutdown(void)
2742 qglDeleteQueriesARB(r_maxqueries, r_queries);
2746 memset(r_queries, 0, sizeof(r_queries));
2748 r_qwskincache = NULL;
2749 r_qwskincache_size = 0;
2751 // clear out the r_skinframe state
2752 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2753 memset(&r_skinframe, 0, sizeof(r_skinframe));
2756 Mem_Free(r_svbsp.nodes);
2757 memset(&r_svbsp, 0, sizeof (r_svbsp));
2758 R_FreeTexturePool(&r_main_texturepool);
2759 loadingscreentexture = NULL;
2760 r_texture_blanknormalmap = NULL;
2761 r_texture_white = NULL;
2762 r_texture_grey128 = NULL;
2763 r_texture_black = NULL;
2764 r_texture_whitecube = NULL;
2765 r_texture_normalizationcube = NULL;
2766 r_texture_fogattenuation = NULL;
2767 r_texture_gammaramps = NULL;
2768 //r_texture_fogintensity = NULL;
2769 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2770 memset(&r_waterstate, 0, sizeof(r_waterstate));
2774 extern void CL_ParseEntityLump(char *entitystring);
2775 void gl_main_newmap(void)
2777 // FIXME: move this code to client
2779 char *entities, entname[MAX_QPATH];
2781 Mem_Free(r_qwskincache);
2782 r_qwskincache = NULL;
2783 r_qwskincache_size = 0;
2786 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2787 l = (int)strlen(entname) - 4;
2788 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2790 memcpy(entname + l, ".ent", 5);
2791 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2793 CL_ParseEntityLump(entities);
2798 if (cl.worldmodel->brush.entities)
2799 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2803 void GL_Main_Init(void)
2805 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2807 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2808 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2809 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2810 if (gamemode == GAME_NEHAHRA)
2812 Cvar_RegisterVariable (&gl_fogenable);
2813 Cvar_RegisterVariable (&gl_fogdensity);
2814 Cvar_RegisterVariable (&gl_fogred);
2815 Cvar_RegisterVariable (&gl_foggreen);
2816 Cvar_RegisterVariable (&gl_fogblue);
2817 Cvar_RegisterVariable (&gl_fogstart);
2818 Cvar_RegisterVariable (&gl_fogend);
2819 Cvar_RegisterVariable (&gl_skyclip);
2821 Cvar_RegisterVariable(&r_motionblur);
2822 Cvar_RegisterVariable(&r_motionblur_maxblur);
2823 Cvar_RegisterVariable(&r_motionblur_bmin);
2824 Cvar_RegisterVariable(&r_motionblur_vmin);
2825 Cvar_RegisterVariable(&r_motionblur_vmax);
2826 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2827 Cvar_RegisterVariable(&r_motionblur_randomize);
2828 Cvar_RegisterVariable(&r_damageblur);
2829 Cvar_RegisterVariable(&r_animcache);
2830 Cvar_RegisterVariable(&r_depthfirst);
2831 Cvar_RegisterVariable(&r_useinfinitefarclip);
2832 Cvar_RegisterVariable(&r_nearclip);
2833 Cvar_RegisterVariable(&r_showbboxes);
2834 Cvar_RegisterVariable(&r_showsurfaces);
2835 Cvar_RegisterVariable(&r_showtris);
2836 Cvar_RegisterVariable(&r_shownormals);
2837 Cvar_RegisterVariable(&r_showlighting);
2838 Cvar_RegisterVariable(&r_showshadowvolumes);
2839 Cvar_RegisterVariable(&r_showcollisionbrushes);
2840 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2841 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2842 Cvar_RegisterVariable(&r_showdisabledepthtest);
2843 Cvar_RegisterVariable(&r_drawportals);
2844 Cvar_RegisterVariable(&r_drawentities);
2845 Cvar_RegisterVariable(&r_cullentities_trace);
2846 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2847 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2848 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2849 Cvar_RegisterVariable(&r_drawviewmodel);
2850 Cvar_RegisterVariable(&r_speeds);
2851 Cvar_RegisterVariable(&r_fullbrights);
2852 Cvar_RegisterVariable(&r_wateralpha);
2853 Cvar_RegisterVariable(&r_dynamic);
2854 Cvar_RegisterVariable(&r_fullbright);
2855 Cvar_RegisterVariable(&r_shadows);
2856 Cvar_RegisterVariable(&r_shadows_darken);
2857 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
2858 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2859 Cvar_RegisterVariable(&r_shadows_throwdistance);
2860 Cvar_RegisterVariable(&r_shadows_throwdirection);
2861 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2862 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2863 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2864 Cvar_RegisterVariable(&r_fog_exp2);
2865 Cvar_RegisterVariable(&r_drawfog);
2866 Cvar_RegisterVariable(&r_textureunits);
2867 Cvar_RegisterVariable(&r_glsl);
2868 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2869 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2870 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2871 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2872 Cvar_RegisterVariable(&r_glsl_postprocess);
2873 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2874 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2875 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2876 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2877 Cvar_RegisterVariable(&r_glsl_usegeneric);
2878 Cvar_RegisterVariable(&r_water);
2879 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2880 Cvar_RegisterVariable(&r_water_clippingplanebias);
2881 Cvar_RegisterVariable(&r_water_refractdistort);
2882 Cvar_RegisterVariable(&r_water_reflectdistort);
2883 Cvar_RegisterVariable(&r_lerpsprites);
2884 Cvar_RegisterVariable(&r_lerpmodels);
2885 Cvar_RegisterVariable(&r_lerplightstyles);
2886 Cvar_RegisterVariable(&r_waterscroll);
2887 Cvar_RegisterVariable(&r_bloom);
2888 Cvar_RegisterVariable(&r_bloom_colorscale);
2889 Cvar_RegisterVariable(&r_bloom_brighten);
2890 Cvar_RegisterVariable(&r_bloom_blur);
2891 Cvar_RegisterVariable(&r_bloom_resolution);
2892 Cvar_RegisterVariable(&r_bloom_colorexponent);
2893 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2894 Cvar_RegisterVariable(&r_hdr);
2895 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2896 Cvar_RegisterVariable(&r_hdr_glowintensity);
2897 Cvar_RegisterVariable(&r_hdr_range);
2898 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2899 Cvar_RegisterVariable(&developer_texturelogging);
2900 Cvar_RegisterVariable(&gl_lightmaps);
2901 Cvar_RegisterVariable(&r_test);
2902 Cvar_RegisterVariable(&r_batchmode);
2903 Cvar_RegisterVariable(&r_glsl_saturation);
2904 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2905 Cvar_SetValue("r_fullbrights", 0);
2906 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2908 Cvar_RegisterVariable(&r_track_sprites);
2909 Cvar_RegisterVariable(&r_track_sprites_flags);
2910 Cvar_RegisterVariable(&r_track_sprites_scalew);
2911 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2914 extern void R_Textures_Init(void);
2915 extern void GL_Draw_Init(void);
2916 extern void GL_Main_Init(void);
2917 extern void R_Shadow_Init(void);
2918 extern void R_Sky_Init(void);
2919 extern void GL_Surf_Init(void);
2920 extern void R_Particles_Init(void);
2921 extern void R_Explosion_Init(void);
2922 extern void gl_backend_init(void);
2923 extern void Sbar_Init(void);
2924 extern void R_LightningBeams_Init(void);
2925 extern void Mod_RenderInit(void);
2927 void Render_Init(void)
2939 R_LightningBeams_Init();
2948 extern char *ENGINE_EXTENSIONS;
2951 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2952 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2953 gl_version = (const char *)qglGetString(GL_VERSION);
2954 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2958 if (!gl_platformextensions)
2959 gl_platformextensions = "";
2961 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2962 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2963 Con_Printf("GL_VERSION: %s\n", gl_version);
2964 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2965 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2967 VID_CheckExtensions();
2969 // LordHavoc: report supported extensions
2970 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2972 // clear to black (loading plaque will be seen over this)
2974 qglClearColor(0,0,0,1);CHECKGLERROR
2975 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2978 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2982 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2984 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2987 p = r_refdef.view.frustum + i;
2992 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2996 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3000 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3004 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3008 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3012 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3016 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3020 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3028 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3032 for (i = 0;i < numplanes;i++)
3039 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3043 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3047 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3051 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3055 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3059 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3063 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3067 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3075 //==================================================================================
3077 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3080 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3081 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3082 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3085 typedef struct r_animcache_entity_s
3092 qboolean wantnormals;
3093 qboolean wanttangents;
3095 r_animcache_entity_t;
3097 typedef struct r_animcache_s
3099 r_animcache_entity_t entity[MAX_EDICTS*2];
3105 static r_animcache_t r_animcachestate;
3107 void R_AnimCache_Free(void)
3110 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3112 r_animcachestate.entity[idx].maxvertices = 0;
3113 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3114 r_animcachestate.entity[idx].vertex3f = NULL;
3115 r_animcachestate.entity[idx].normal3f = NULL;
3116 r_animcachestate.entity[idx].svector3f = NULL;
3117 r_animcachestate.entity[idx].tvector3f = NULL;
3119 r_animcachestate.currentindex = 0;
3120 r_animcachestate.maxindex = 0;
3123 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3127 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3129 if (cache->maxvertices >= numvertices)
3132 // Release existing memory
3133 if (cache->vertex3f)
3134 Mem_Free(cache->vertex3f);
3136 // Pad by 1024 verts
3137 cache->maxvertices = (numvertices + 1023) & ~1023;
3138 arraySize = cache->maxvertices * 3;
3140 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3141 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3142 r_animcachestate.entity[cacheIdx].vertex3f = base;
3143 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3144 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3145 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3147 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3150 void R_AnimCache_NewFrame(void)
3154 if (r_animcache.integer && r_drawentities.integer)
3155 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3156 else if (r_animcachestate.maxindex)
3159 r_animcachestate.currentindex = 0;
3161 for (i = 0;i < r_refdef.scene.numentities;i++)
3162 r_refdef.scene.entities[i]->animcacheindex = -1;
3165 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3167 dp_model_t *model = ent->model;
3168 r_animcache_entity_t *c;
3169 // see if it's already cached this frame
3170 if (ent->animcacheindex >= 0)
3172 // add normals/tangents if needed
3173 c = r_animcachestate.entity + ent->animcacheindex;
3175 wantnormals = false;
3176 if (c->wanttangents)
3177 wanttangents = false;
3178 if (wantnormals || wanttangents)
3179 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3183 // see if this ent is worth caching
3184 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3186 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3188 // assign it a cache entry and make sure the arrays are big enough
3189 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3190 ent->animcacheindex = r_animcachestate.currentindex++;
3191 c = r_animcachestate.entity + ent->animcacheindex;
3192 c->wantnormals = wantnormals;
3193 c->wanttangents = wanttangents;
3194 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3199 void R_AnimCache_CacheVisibleEntities(void)
3202 qboolean wantnormals;
3203 qboolean wanttangents;
3205 if (!r_animcachestate.maxindex)
3208 wantnormals = !r_showsurfaces.integer;
3209 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3211 // TODO: thread this?
3213 for (i = 0;i < r_refdef.scene.numentities;i++)
3215 if (!r_refdef.viewcache.entityvisible[i])
3217 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3221 //==================================================================================
3223 static void R_View_UpdateEntityLighting (void)
3226 entity_render_t *ent;
3227 vec3_t tempdiffusenormal;
3229 for (i = 0;i < r_refdef.scene.numentities;i++)
3231 ent = r_refdef.scene.entities[i];
3233 // skip unseen models
3234 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3238 if (ent->model && ent->model->brush.num_leafs)
3240 // TODO: use modellight for r_ambient settings on world?
3241 VectorSet(ent->modellight_ambient, 0, 0, 0);
3242 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3243 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3247 // fetch the lighting from the worldmodel data
3248 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));
3249 VectorClear(ent->modellight_diffuse);
3250 VectorClear(tempdiffusenormal);
3251 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3254 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3255 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3258 VectorSet(ent->modellight_ambient, 1, 1, 1);
3260 // move the light direction into modelspace coordinates for lighting code
3261 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3262 if(VectorLength2(ent->modellight_lightdir) == 0)
3263 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3264 VectorNormalize(ent->modellight_lightdir);
3268 #define MAX_LINEOFSIGHTTRACES 64
3270 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3273 vec3_t boxmins, boxmaxs;
3276 dp_model_t *model = r_refdef.scene.worldmodel;
3278 if (!model || !model->brush.TraceLineOfSight)
3281 // expand the box a little
3282 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3283 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3284 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3285 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3286 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3287 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3290 VectorCopy(eye, start);
3291 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3292 if (model->brush.TraceLineOfSight(model, start, end))
3295 // try various random positions
3296 for (i = 0;i < numsamples;i++)
3298 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3299 if (model->brush.TraceLineOfSight(model, start, end))
3307 static void R_View_UpdateEntityVisible (void)
3310 entity_render_t *ent;
3312 if (!r_drawentities.integer)
3315 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3316 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3318 // worldmodel can check visibility
3319 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3320 for (i = 0;i < r_refdef.scene.numentities;i++)
3322 ent = r_refdef.scene.entities[i];
3323 if (!(ent->flags & renderimask))
3324 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)))
3325 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))
3326 r_refdef.viewcache.entityvisible[i] = true;
3328 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3330 for (i = 0;i < r_refdef.scene.numentities;i++)
3332 ent = r_refdef.scene.entities[i];
3333 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & (RENDER_VIEWMODEL + RENDER_NOCULL)) && !(ent->model && (ent->model->name[0] == '*')))
3335 if(R_CanSeeBox(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3336 ent->last_trace_visibility = realtime;
3337 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3338 r_refdef.viewcache.entityvisible[i] = 0;
3345 // no worldmodel or it can't check visibility
3346 for (i = 0;i < r_refdef.scene.numentities;i++)
3348 ent = r_refdef.scene.entities[i];
3349 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));
3354 /// only used if skyrendermasked, and normally returns false
3355 int R_DrawBrushModelsSky (void)
3358 entity_render_t *ent;
3360 if (!r_drawentities.integer)
3364 for (i = 0;i < r_refdef.scene.numentities;i++)
3366 if (!r_refdef.viewcache.entityvisible[i])
3368 ent = r_refdef.scene.entities[i];
3369 if (!ent->model || !ent->model->DrawSky)
3371 ent->model->DrawSky(ent);
3377 static void R_DrawNoModel(entity_render_t *ent);
3378 static void R_DrawModels(void)
3381 entity_render_t *ent;
3383 if (!r_drawentities.integer)
3386 for (i = 0;i < r_refdef.scene.numentities;i++)
3388 if (!r_refdef.viewcache.entityvisible[i])
3390 ent = r_refdef.scene.entities[i];
3391 r_refdef.stats.entities++;
3392 if (ent->model && ent->model->Draw != NULL)
3393 ent->model->Draw(ent);
3399 static void R_DrawModelsDepth(void)
3402 entity_render_t *ent;
3404 if (!r_drawentities.integer)
3407 for (i = 0;i < r_refdef.scene.numentities;i++)
3409 if (!r_refdef.viewcache.entityvisible[i])
3411 ent = r_refdef.scene.entities[i];
3412 if (ent->model && ent->model->DrawDepth != NULL)
3413 ent->model->DrawDepth(ent);
3417 static void R_DrawModelsDebug(void)
3420 entity_render_t *ent;
3422 if (!r_drawentities.integer)
3425 for (i = 0;i < r_refdef.scene.numentities;i++)
3427 if (!r_refdef.viewcache.entityvisible[i])
3429 ent = r_refdef.scene.entities[i];
3430 if (ent->model && ent->model->DrawDebug != NULL)
3431 ent->model->DrawDebug(ent);
3435 static void R_DrawModelsAddWaterPlanes(void)
3438 entity_render_t *ent;
3440 if (!r_drawentities.integer)
3443 for (i = 0;i < r_refdef.scene.numentities;i++)
3445 if (!r_refdef.viewcache.entityvisible[i])
3447 ent = r_refdef.scene.entities[i];
3448 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3449 ent->model->DrawAddWaterPlanes(ent);
3453 static void R_View_SetFrustum(void)
3456 double slopex, slopey;
3457 vec3_t forward, left, up, origin;
3459 // we can't trust r_refdef.view.forward and friends in reflected scenes
3460 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3463 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3464 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3465 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3466 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3467 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3468 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3469 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3470 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3471 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3472 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3473 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3474 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3478 zNear = r_refdef.nearclip;
3479 nudge = 1.0 - 1.0 / (1<<23);
3480 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3481 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3482 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3483 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3484 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3485 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3486 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3487 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3493 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3494 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3495 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3496 r_refdef.view.frustum[0].dist = m[15] - m[12];
3498 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3499 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3500 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3501 r_refdef.view.frustum[1].dist = m[15] + m[12];
3503 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3504 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3505 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3506 r_refdef.view.frustum[2].dist = m[15] - m[13];
3508 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3509 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3510 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3511 r_refdef.view.frustum[3].dist = m[15] + m[13];
3513 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3514 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3515 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3516 r_refdef.view.frustum[4].dist = m[15] - m[14];
3518 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3519 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3520 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3521 r_refdef.view.frustum[5].dist = m[15] + m[14];
3524 if (r_refdef.view.useperspective)
3526 slopex = 1.0 / r_refdef.view.frustum_x;
3527 slopey = 1.0 / r_refdef.view.frustum_y;
3528 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3529 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3530 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3531 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3532 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3534 // Leaving those out was a mistake, those were in the old code, and they
3535 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3536 // I couldn't reproduce it after adding those normalizations. --blub
3537 VectorNormalize(r_refdef.view.frustum[0].normal);
3538 VectorNormalize(r_refdef.view.frustum[1].normal);
3539 VectorNormalize(r_refdef.view.frustum[2].normal);
3540 VectorNormalize(r_refdef.view.frustum[3].normal);
3542 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3543 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]);
3544 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]);
3545 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]);
3546 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]);
3548 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3549 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3550 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3551 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3552 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3556 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3557 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3558 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3559 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3560 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3561 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3562 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3563 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3564 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3565 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3567 r_refdef.view.numfrustumplanes = 5;
3569 if (r_refdef.view.useclipplane)
3571 r_refdef.view.numfrustumplanes = 6;
3572 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3575 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3576 PlaneClassify(r_refdef.view.frustum + i);
3578 // LordHavoc: note to all quake engine coders, Quake had a special case
3579 // for 90 degrees which assumed a square view (wrong), so I removed it,
3580 // Quake2 has it disabled as well.
3582 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3583 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3584 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3585 //PlaneClassify(&frustum[0]);
3587 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3588 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3589 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3590 //PlaneClassify(&frustum[1]);
3592 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3593 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3594 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3595 //PlaneClassify(&frustum[2]);
3597 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3598 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3599 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3600 //PlaneClassify(&frustum[3]);
3603 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3604 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3605 //PlaneClassify(&frustum[4]);
3608 void R_View_Update(void)
3610 R_View_SetFrustum();
3611 R_View_WorldVisibility(r_refdef.view.useclipplane);
3612 R_View_UpdateEntityVisible();
3613 R_View_UpdateEntityLighting();
3616 void R_SetupView(qboolean allowwaterclippingplane)
3618 const double *customclipplane = NULL;
3620 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3622 // LordHavoc: couldn't figure out how to make this approach the
3623 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3624 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3625 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3626 dist = r_refdef.view.clipplane.dist;
3627 plane[0] = r_refdef.view.clipplane.normal[0];
3628 plane[1] = r_refdef.view.clipplane.normal[1];
3629 plane[2] = r_refdef.view.clipplane.normal[2];
3631 customclipplane = plane;
3634 if (!r_refdef.view.useperspective)
3635 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);
3636 else if (gl_stencil && r_useinfinitefarclip.integer)
3637 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);
3639 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);
3640 R_SetViewport(&r_refdef.view.viewport);
3643 void R_ResetViewRendering2D(void)
3645 r_viewport_t viewport;
3648 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3649 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);
3650 R_SetViewport(&viewport);
3651 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3652 GL_Color(1, 1, 1, 1);
3653 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3654 GL_BlendFunc(GL_ONE, GL_ZERO);
3655 GL_AlphaTest(false);
3656 GL_ScissorTest(false);
3657 GL_DepthMask(false);
3658 GL_DepthRange(0, 1);
3659 GL_DepthTest(false);
3660 R_Mesh_Matrix(&identitymatrix);
3661 R_Mesh_ResetTextureState();
3662 GL_PolygonOffset(0, 0);
3663 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3664 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3665 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3666 qglStencilMask(~0);CHECKGLERROR
3667 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3668 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3669 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3670 R_SetupGenericShader(true);
3673 void R_ResetViewRendering3D(void)
3678 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3679 GL_Color(1, 1, 1, 1);
3680 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3681 GL_BlendFunc(GL_ONE, GL_ZERO);
3682 GL_AlphaTest(false);
3683 GL_ScissorTest(true);
3685 GL_DepthRange(0, 1);
3687 R_Mesh_Matrix(&identitymatrix);
3688 R_Mesh_ResetTextureState();
3689 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3690 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3691 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3692 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3693 qglStencilMask(~0);CHECKGLERROR
3694 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3695 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3696 GL_CullFace(r_refdef.view.cullface_back);
3697 R_SetupGenericShader(true);
3700 void R_RenderScene(void);
3701 void R_RenderWaterPlanes(void);
3703 static void R_Water_StartFrame(void)
3706 int waterwidth, waterheight, texturewidth, textureheight;
3707 r_waterstate_waterplane_t *p;
3709 // set waterwidth and waterheight to the water resolution that will be
3710 // used (often less than the screen resolution for faster rendering)
3711 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3712 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3714 // calculate desired texture sizes
3715 // can't use water if the card does not support the texture size
3716 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3717 texturewidth = textureheight = waterwidth = waterheight = 0;
3718 else if (gl_support_arb_texture_non_power_of_two)
3720 texturewidth = waterwidth;
3721 textureheight = waterheight;
3725 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3726 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3729 // allocate textures as needed
3730 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3732 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3733 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3735 if (p->texture_refraction)
3736 R_FreeTexture(p->texture_refraction);
3737 p->texture_refraction = NULL;
3738 if (p->texture_reflection)
3739 R_FreeTexture(p->texture_reflection);
3740 p->texture_reflection = NULL;
3742 memset(&r_waterstate, 0, sizeof(r_waterstate));
3743 r_waterstate.texturewidth = texturewidth;
3744 r_waterstate.textureheight = textureheight;
3747 if (r_waterstate.texturewidth)
3749 r_waterstate.enabled = true;
3751 // when doing a reduced render (HDR) we want to use a smaller area
3752 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3753 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3755 // set up variables that will be used in shader setup
3756 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3757 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3758 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3759 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3762 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3763 r_waterstate.numwaterplanes = 0;
3766 void R_Water_AddWaterPlane(msurface_t *surface)
3768 int triangleindex, planeindex;
3774 r_waterstate_waterplane_t *p;
3775 texture_t *t = R_GetCurrentTexture(surface->texture);
3776 // just use the first triangle with a valid normal for any decisions
3777 VectorClear(normal);
3778 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3780 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3781 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3782 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3783 TriangleNormal(vert[0], vert[1], vert[2], normal);
3784 if (VectorLength2(normal) >= 0.001)
3788 VectorCopy(normal, plane.normal);
3789 VectorNormalize(plane.normal);
3790 plane.dist = DotProduct(vert[0], plane.normal);
3791 PlaneClassify(&plane);
3792 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3794 // skip backfaces (except if nocullface is set)
3795 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3797 VectorNegate(plane.normal, plane.normal);
3799 PlaneClassify(&plane);
3803 // find a matching plane if there is one
3804 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3805 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3807 if (planeindex >= r_waterstate.maxwaterplanes)
3808 return; // nothing we can do, out of planes
3810 // if this triangle does not fit any known plane rendered this frame, add one
3811 if (planeindex >= r_waterstate.numwaterplanes)
3813 // store the new plane
3814 r_waterstate.numwaterplanes++;
3816 // clear materialflags and pvs
3817 p->materialflags = 0;
3818 p->pvsvalid = false;
3820 // merge this surface's materialflags into the waterplane
3821 p->materialflags |= t->currentmaterialflags;
3822 // merge this surface's PVS into the waterplane
3823 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3824 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3825 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3827 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3832 static void R_Water_ProcessPlanes(void)
3834 r_refdef_view_t originalview;
3835 r_refdef_view_t myview;
3837 r_waterstate_waterplane_t *p;
3839 originalview = r_refdef.view;
3841 // make sure enough textures are allocated
3842 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3844 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3846 if (!p->texture_refraction)
3847 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);
3848 if (!p->texture_refraction)
3852 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3854 if (!p->texture_reflection)
3855 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);
3856 if (!p->texture_reflection)
3862 r_refdef.view = originalview;
3863 r_refdef.view.showdebug = false;
3864 r_refdef.view.width = r_waterstate.waterwidth;
3865 r_refdef.view.height = r_waterstate.waterheight;
3866 r_refdef.view.useclipplane = true;
3867 myview = r_refdef.view;
3868 r_waterstate.renderingscene = true;
3869 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3871 // render the normal view scene and copy into texture
3872 // (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)
3873 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3875 r_refdef.view = myview;
3876 r_refdef.view.clipplane = p->plane;
3877 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3878 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3879 PlaneClassify(&r_refdef.view.clipplane);
3881 R_ResetViewRendering3D();
3882 R_ClearScreen(r_refdef.fogenabled);
3886 // copy view into the screen texture
3887 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3888 GL_ActiveTexture(0);
3890 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
3893 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3895 r_refdef.view = myview;
3896 // render reflected scene and copy into texture
3897 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3898 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3899 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3900 r_refdef.view.clipplane = p->plane;
3901 // reverse the cullface settings for this render
3902 r_refdef.view.cullface_front = GL_FRONT;
3903 r_refdef.view.cullface_back = GL_BACK;
3904 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3906 r_refdef.view.usecustompvs = true;
3908 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3910 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3913 R_ResetViewRendering3D();
3914 R_ClearScreen(r_refdef.fogenabled);
3918 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3919 GL_ActiveTexture(0);
3921 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
3924 r_waterstate.renderingscene = false;
3925 r_refdef.view = originalview;
3926 R_ResetViewRendering3D();
3927 R_ClearScreen(r_refdef.fogenabled);
3931 r_refdef.view = originalview;
3932 r_waterstate.renderingscene = false;
3933 Cvar_SetValueQuick(&r_water, 0);
3934 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3938 void R_Bloom_StartFrame(void)
3940 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3942 // set bloomwidth and bloomheight to the bloom resolution that will be
3943 // used (often less than the screen resolution for faster rendering)
3944 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
3945 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
3946 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
3947 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
3948 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
3950 // calculate desired texture sizes
3951 if (gl_support_arb_texture_non_power_of_two)
3953 screentexturewidth = r_refdef.view.width;
3954 screentextureheight = r_refdef.view.height;
3955 bloomtexturewidth = r_bloomstate.bloomwidth;
3956 bloomtextureheight = r_bloomstate.bloomheight;
3960 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3961 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3962 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3963 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3966 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))
3968 Cvar_SetValueQuick(&r_hdr, 0);
3969 Cvar_SetValueQuick(&r_bloom, 0);
3970 Cvar_SetValueQuick(&r_motionblur, 0);
3971 Cvar_SetValueQuick(&r_damageblur, 0);
3974 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)))
3975 screentexturewidth = screentextureheight = 0;
3976 if (!r_hdr.integer && !r_bloom.integer)
3977 bloomtexturewidth = bloomtextureheight = 0;
3979 // allocate textures as needed
3980 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3982 if (r_bloomstate.texture_screen)
3983 R_FreeTexture(r_bloomstate.texture_screen);
3984 r_bloomstate.texture_screen = NULL;
3985 r_bloomstate.screentexturewidth = screentexturewidth;
3986 r_bloomstate.screentextureheight = screentextureheight;
3987 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3988 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);
3990 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3992 if (r_bloomstate.texture_bloom)
3993 R_FreeTexture(r_bloomstate.texture_bloom);
3994 r_bloomstate.texture_bloom = NULL;
3995 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3996 r_bloomstate.bloomtextureheight = bloomtextureheight;
3997 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3998 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);
4001 // when doing a reduced render (HDR) we want to use a smaller area
4002 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4003 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4004 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4005 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4006 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4008 // set up a texcoord array for the full resolution screen image
4009 // (we have to keep this around to copy back during final render)
4010 r_bloomstate.screentexcoord2f[0] = 0;
4011 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4012 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4013 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4014 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4015 r_bloomstate.screentexcoord2f[5] = 0;
4016 r_bloomstate.screentexcoord2f[6] = 0;
4017 r_bloomstate.screentexcoord2f[7] = 0;
4019 // set up a texcoord array for the reduced resolution bloom image
4020 // (which will be additive blended over the screen image)
4021 r_bloomstate.bloomtexcoord2f[0] = 0;
4022 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4023 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4024 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4025 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4026 r_bloomstate.bloomtexcoord2f[5] = 0;
4027 r_bloomstate.bloomtexcoord2f[6] = 0;
4028 r_bloomstate.bloomtexcoord2f[7] = 0;
4030 if (r_hdr.integer || r_bloom.integer)
4032 r_bloomstate.enabled = true;
4033 r_bloomstate.hdr = r_hdr.integer != 0;
4036 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);
4039 void R_Bloom_CopyBloomTexture(float colorscale)
4041 r_refdef.stats.bloom++;
4043 // scale down screen texture to the bloom texture size
4045 R_SetViewport(&r_bloomstate.viewport);
4046 GL_BlendFunc(GL_ONE, GL_ZERO);
4047 GL_Color(colorscale, colorscale, colorscale, 1);
4048 // TODO: optimize with multitexture or GLSL
4049 R_SetupGenericShader(true);
4050 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4051 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4052 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4053 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4055 // we now have a bloom image in the framebuffer
4056 // copy it into the bloom image texture for later processing
4057 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4058 GL_ActiveTexture(0);
4060 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4061 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4064 void R_Bloom_CopyHDRTexture(void)
4066 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4067 GL_ActiveTexture(0);
4069 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
4070 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4073 void R_Bloom_MakeTexture(void)
4076 float xoffset, yoffset, r, brighten;
4078 r_refdef.stats.bloom++;
4080 R_ResetViewRendering2D();
4081 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4082 R_Mesh_ColorPointer(NULL, 0, 0);
4083 R_SetupGenericShader(true);
4085 // we have a bloom image in the framebuffer
4087 R_SetViewport(&r_bloomstate.viewport);
4089 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4092 r = bound(0, r_bloom_colorexponent.value / x, 1);
4093 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4094 GL_Color(r, r, r, 1);
4095 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4096 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4097 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4098 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4100 // copy the vertically blurred bloom view to a texture
4101 GL_ActiveTexture(0);
4103 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4104 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4107 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4108 brighten = r_bloom_brighten.value;
4110 brighten *= r_hdr_range.value;
4111 brighten = sqrt(brighten);
4113 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4114 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4115 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4117 for (dir = 0;dir < 2;dir++)
4119 // blend on at multiple vertical offsets to achieve a vertical blur
4120 // TODO: do offset blends using GLSL
4121 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4122 GL_BlendFunc(GL_ONE, GL_ZERO);
4123 for (x = -range;x <= range;x++)
4125 if (!dir){xoffset = 0;yoffset = x;}
4126 else {xoffset = x;yoffset = 0;}
4127 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4128 yoffset /= (float)r_bloomstate.bloomtextureheight;
4129 // compute a texcoord array with the specified x and y offset
4130 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4131 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4132 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4133 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4134 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4135 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4136 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4137 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4138 // this r value looks like a 'dot' particle, fading sharply to
4139 // black at the edges
4140 // (probably not realistic but looks good enough)
4141 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4142 //r = brighten/(range*2+1);
4143 r = brighten / (range * 2 + 1);
4145 r *= (1 - x*x/(float)(range*range));
4146 GL_Color(r, r, r, 1);
4147 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4148 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4149 GL_BlendFunc(GL_ONE, GL_ONE);
4152 // copy the vertically blurred bloom view to a texture
4153 GL_ActiveTexture(0);
4155 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4156 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4159 // apply subtract last
4160 // (just like it would be in a GLSL shader)
4161 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4163 GL_BlendFunc(GL_ONE, GL_ZERO);
4164 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4165 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4166 GL_Color(1, 1, 1, 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;
4170 GL_BlendFunc(GL_ONE, GL_ONE);
4171 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4172 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4173 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4174 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4175 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4176 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4177 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4179 // copy the darkened bloom view to a texture
4180 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4181 GL_ActiveTexture(0);
4183 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4184 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4188 void R_HDR_RenderBloomTexture(void)
4190 int oldwidth, oldheight;
4191 float oldcolorscale;
4193 oldcolorscale = r_refdef.view.colorscale;
4194 oldwidth = r_refdef.view.width;
4195 oldheight = r_refdef.view.height;
4196 r_refdef.view.width = r_bloomstate.bloomwidth;
4197 r_refdef.view.height = r_bloomstate.bloomheight;
4199 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4200 // TODO: add exposure compensation features
4201 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4203 r_refdef.view.showdebug = false;
4204 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4206 R_ResetViewRendering3D();
4208 R_ClearScreen(r_refdef.fogenabled);
4209 if (r_timereport_active)
4210 R_TimeReport("HDRclear");
4213 if (r_timereport_active)
4214 R_TimeReport("visibility");
4216 // only do secondary renders with HDR if r_hdr is 2 or higher
4217 r_waterstate.numwaterplanes = 0;
4218 if (r_waterstate.enabled && r_hdr.integer >= 2)
4219 R_RenderWaterPlanes();
4221 r_refdef.view.showdebug = true;
4223 r_waterstate.numwaterplanes = 0;
4225 R_ResetViewRendering2D();
4227 R_Bloom_CopyHDRTexture();
4228 R_Bloom_MakeTexture();
4230 // restore the view settings
4231 r_refdef.view.width = oldwidth;
4232 r_refdef.view.height = oldheight;
4233 r_refdef.view.colorscale = oldcolorscale;
4235 R_ResetViewRendering3D();
4237 R_ClearScreen(r_refdef.fogenabled);
4238 if (r_timereport_active)
4239 R_TimeReport("viewclear");
4242 static void R_BlendView(void)
4244 if (r_bloomstate.texture_screen)
4246 // make sure the buffer is available
4247 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4249 R_ResetViewRendering2D();
4250 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4251 R_Mesh_ColorPointer(NULL, 0, 0);
4252 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4253 GL_ActiveTexture(0);CHECKGLERROR
4255 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4257 // declare variables
4259 static float avgspeed;
4261 speed = VectorLength(cl.movement_velocity);
4263 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4264 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4266 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4267 speed = bound(0, speed, 1);
4268 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4270 // calculate values into a standard alpha
4271 cl.motionbluralpha = 1 - exp(-
4273 (r_motionblur.value * speed / 80)
4275 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4278 max(0.0001, cl.time - cl.oldtime) // fps independent
4281 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4282 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4284 if (cl.motionbluralpha > 0)
4286 R_SetupGenericShader(true);
4287 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4288 GL_Color(1, 1, 1, cl.motionbluralpha);
4289 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4290 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4291 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4292 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4296 // copy view into the screen texture
4297 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
4298 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4301 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4303 unsigned int permutation =
4304 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4305 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4306 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4307 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4308 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4310 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4312 // render simple bloom effect
4313 // copy the screen and shrink it and darken it for the bloom process
4314 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4315 // make the bloom texture
4316 R_Bloom_MakeTexture();
4319 R_ResetViewRendering2D();
4320 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4321 R_Mesh_ColorPointer(NULL, 0, 0);
4322 GL_Color(1, 1, 1, 1);
4323 GL_BlendFunc(GL_ONE, GL_ZERO);
4324 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4325 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4326 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4327 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4328 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4329 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4330 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4331 if (r_glsl_permutation->loc_TintColor >= 0)
4332 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4333 if (r_glsl_permutation->loc_ClientTime >= 0)
4334 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4335 if (r_glsl_permutation->loc_PixelSize >= 0)
4336 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4337 if (r_glsl_permutation->loc_UserVec1 >= 0)
4339 float a=0, b=0, c=0, d=0;
4340 #if _MSC_VER >= 1400
4341 #define sscanf sscanf_s
4343 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4344 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4346 if (r_glsl_permutation->loc_UserVec2 >= 0)
4348 float a=0, b=0, c=0, d=0;
4349 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4350 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4352 if (r_glsl_permutation->loc_UserVec3 >= 0)
4354 float a=0, b=0, c=0, d=0;
4355 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4356 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4358 if (r_glsl_permutation->loc_UserVec4 >= 0)
4360 float a=0, b=0, c=0, d=0;
4361 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4362 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4364 if (r_glsl_permutation->loc_Saturation >= 0)
4365 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4366 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4367 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4373 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4375 // render high dynamic range bloom effect
4376 // the bloom texture was made earlier this render, so we just need to
4377 // blend it onto the screen...
4378 R_ResetViewRendering2D();
4379 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4380 R_Mesh_ColorPointer(NULL, 0, 0);
4381 R_SetupGenericShader(true);
4382 GL_Color(1, 1, 1, 1);
4383 GL_BlendFunc(GL_ONE, GL_ONE);
4384 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4385 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
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;
4389 else if (r_bloomstate.texture_bloom)
4391 // render simple bloom effect
4392 // copy the screen and shrink it and darken it for the bloom process
4393 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4394 // make the bloom texture
4395 R_Bloom_MakeTexture();
4396 // put the original screen image back in place and blend the bloom
4398 R_ResetViewRendering2D();
4399 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4400 R_Mesh_ColorPointer(NULL, 0, 0);
4401 GL_Color(1, 1, 1, 1);
4402 GL_BlendFunc(GL_ONE, GL_ZERO);
4403 // do both in one pass if possible
4404 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4405 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4406 if (r_textureunits.integer >= 2 && gl_combine.integer)
4408 R_SetupGenericTwoTextureShader(GL_ADD);
4409 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4410 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4414 R_SetupGenericShader(true);
4415 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4416 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4417 // now blend on the bloom texture
4418 GL_BlendFunc(GL_ONE, GL_ONE);
4419 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4420 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4422 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4423 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4425 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4427 // apply a color tint to the whole view
4428 R_ResetViewRendering2D();
4429 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4430 R_Mesh_ColorPointer(NULL, 0, 0);
4431 R_SetupGenericShader(false);
4432 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4433 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4434 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4438 matrix4x4_t r_waterscrollmatrix;
4440 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4442 if (r_refdef.fog_density)
4444 r_refdef.fogcolor[0] = r_refdef.fog_red;
4445 r_refdef.fogcolor[1] = r_refdef.fog_green;
4446 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4450 VectorCopy(r_refdef.fogcolor, fogvec);
4451 // color.rgb *= ContrastBoost * SceneBrightness;
4452 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4453 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4454 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4455 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4460 void R_UpdateVariables(void)
4464 r_refdef.scene.ambient = r_ambient.value;
4466 r_refdef.farclip = 4096;
4467 if (r_refdef.scene.worldmodel)
4468 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4469 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4471 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4472 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4473 r_refdef.polygonfactor = 0;
4474 r_refdef.polygonoffset = 0;
4475 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4476 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4478 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4479 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4480 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4481 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4482 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4483 if (r_showsurfaces.integer)
4485 r_refdef.scene.rtworld = false;
4486 r_refdef.scene.rtworldshadows = false;
4487 r_refdef.scene.rtdlight = false;
4488 r_refdef.scene.rtdlightshadows = false;
4489 r_refdef.lightmapintensity = 0;
4492 if (gamemode == GAME_NEHAHRA)
4494 if (gl_fogenable.integer)
4496 r_refdef.oldgl_fogenable = true;
4497 r_refdef.fog_density = gl_fogdensity.value;
4498 r_refdef.fog_red = gl_fogred.value;
4499 r_refdef.fog_green = gl_foggreen.value;
4500 r_refdef.fog_blue = gl_fogblue.value;
4501 r_refdef.fog_alpha = 1;
4502 r_refdef.fog_start = 0;
4503 r_refdef.fog_end = gl_skyclip.value;
4505 else if (r_refdef.oldgl_fogenable)
4507 r_refdef.oldgl_fogenable = false;
4508 r_refdef.fog_density = 0;
4509 r_refdef.fog_red = 0;
4510 r_refdef.fog_green = 0;
4511 r_refdef.fog_blue = 0;
4512 r_refdef.fog_alpha = 0;
4513 r_refdef.fog_start = 0;
4514 r_refdef.fog_end = 0;
4518 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4519 r_refdef.fog_start = max(0, r_refdef.fog_start);
4520 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4522 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4524 if (r_refdef.fog_density && r_drawfog.integer)
4526 r_refdef.fogenabled = true;
4527 // this is the point where the fog reaches 0.9986 alpha, which we
4528 // consider a good enough cutoff point for the texture
4529 // (0.9986 * 256 == 255.6)
4530 if (r_fog_exp2.integer)
4531 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4533 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4534 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4535 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4536 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4537 // fog color was already set
4538 // update the fog texture
4539 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)
4540 R_BuildFogTexture();
4543 r_refdef.fogenabled = false;
4545 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4547 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4549 // build GLSL gamma texture
4550 #define RAMPWIDTH 256
4551 unsigned short ramp[RAMPWIDTH * 3];
4552 unsigned char rampbgr[RAMPWIDTH][4];
4555 r_texture_gammaramps_serial = vid_gammatables_serial;
4557 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4558 for(i = 0; i < RAMPWIDTH; ++i)
4560 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4561 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4562 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4565 if (r_texture_gammaramps)
4567 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4571 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);
4577 // remove GLSL gamma texture
4581 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4582 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4588 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4589 if( scenetype != r_currentscenetype ) {
4590 // store the old scenetype
4591 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4592 r_currentscenetype = scenetype;
4593 // move in the new scene
4594 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4603 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4605 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4606 if( scenetype == r_currentscenetype ) {
4607 return &r_refdef.scene;
4609 return &r_scenes_store[ scenetype ];
4618 void R_RenderView(void)
4620 if (r_timereport_active)
4621 R_TimeReport("start");
4622 r_frame++; // used only by R_GetCurrentTexture
4623 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4625 R_AnimCache_NewFrame();
4627 if (r_refdef.view.isoverlay)
4629 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4630 GL_Clear( GL_DEPTH_BUFFER_BIT );
4631 R_TimeReport("depthclear");
4633 r_refdef.view.showdebug = false;
4635 r_waterstate.enabled = false;
4636 r_waterstate.numwaterplanes = 0;
4644 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4645 return; //Host_Error ("R_RenderView: NULL worldmodel");
4647 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4649 // break apart the view matrix into vectors for various purposes
4650 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4651 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4652 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4653 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4654 // make an inverted copy of the view matrix for tracking sprites
4655 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4657 R_Shadow_UpdateWorldLightSelection();
4659 R_Bloom_StartFrame();
4660 R_Water_StartFrame();
4663 if (r_timereport_active)
4664 R_TimeReport("viewsetup");
4666 R_ResetViewRendering3D();
4668 if (r_refdef.view.clear || r_refdef.fogenabled)
4670 R_ClearScreen(r_refdef.fogenabled);
4671 if (r_timereport_active)
4672 R_TimeReport("viewclear");
4674 r_refdef.view.clear = true;
4676 // this produces a bloom texture to be used in R_BlendView() later
4678 R_HDR_RenderBloomTexture();
4680 r_refdef.view.showdebug = true;
4683 if (r_timereport_active)
4684 R_TimeReport("visibility");
4686 r_waterstate.numwaterplanes = 0;
4687 if (r_waterstate.enabled)
4688 R_RenderWaterPlanes();
4691 r_waterstate.numwaterplanes = 0;
4694 if (r_timereport_active)
4695 R_TimeReport("blendview");
4697 GL_Scissor(0, 0, vid.width, vid.height);
4698 GL_ScissorTest(false);
4702 void R_RenderWaterPlanes(void)
4704 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4706 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4707 if (r_timereport_active)
4708 R_TimeReport("waterworld");
4711 // don't let sound skip if going slow
4712 if (r_refdef.scene.extraupdate)
4715 R_DrawModelsAddWaterPlanes();
4716 if (r_timereport_active)
4717 R_TimeReport("watermodels");
4719 if (r_waterstate.numwaterplanes)
4721 R_Water_ProcessPlanes();
4722 if (r_timereport_active)
4723 R_TimeReport("waterscenes");
4727 extern void R_DrawLightningBeams (void);
4728 extern void VM_CL_AddPolygonsToMeshQueue (void);
4729 extern void R_DrawPortals (void);
4730 extern cvar_t cl_locs_show;
4731 static void R_DrawLocs(void);
4732 static void R_DrawEntityBBoxes(void);
4733 void R_RenderScene(void)
4735 r_refdef.stats.renders++;
4739 // don't let sound skip if going slow
4740 if (r_refdef.scene.extraupdate)
4743 R_MeshQueue_BeginScene();
4747 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);
4749 if (cl.csqc_vidvars.drawworld)
4751 // don't let sound skip if going slow
4752 if (r_refdef.scene.extraupdate)
4755 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4757 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4758 if (r_timereport_active)
4759 R_TimeReport("worldsky");
4762 if (R_DrawBrushModelsSky() && r_timereport_active)
4763 R_TimeReport("bmodelsky");
4766 R_AnimCache_CacheVisibleEntities();
4768 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4770 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4771 if (r_timereport_active)
4772 R_TimeReport("worlddepth");
4774 if (r_depthfirst.integer >= 2)
4776 R_DrawModelsDepth();
4777 if (r_timereport_active)
4778 R_TimeReport("modeldepth");
4781 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4783 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4784 if (r_timereport_active)
4785 R_TimeReport("world");
4788 // don't let sound skip if going slow
4789 if (r_refdef.scene.extraupdate)
4793 if (r_timereport_active)
4794 R_TimeReport("models");
4796 // don't let sound skip if going slow
4797 if (r_refdef.scene.extraupdate)
4800 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4802 R_DrawModelShadows();
4803 R_ResetViewRendering3D();
4804 // don't let sound skip if going slow
4805 if (r_refdef.scene.extraupdate)
4809 R_ShadowVolumeLighting(false);
4810 if (r_timereport_active)
4811 R_TimeReport("rtlights");
4813 // don't let sound skip if going slow
4814 if (r_refdef.scene.extraupdate)
4817 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4819 R_DrawModelShadows();
4820 R_ResetViewRendering3D();
4821 // don't let sound skip if going slow
4822 if (r_refdef.scene.extraupdate)
4826 if (cl.csqc_vidvars.drawworld)
4828 R_DrawLightningBeams();
4829 if (r_timereport_active)
4830 R_TimeReport("lightning");
4833 if (r_timereport_active)
4834 R_TimeReport("decals");
4837 if (r_timereport_active)
4838 R_TimeReport("particles");
4841 if (r_timereport_active)
4842 R_TimeReport("explosions");
4845 R_SetupGenericShader(true);
4846 VM_CL_AddPolygonsToMeshQueue();
4848 if (r_refdef.view.showdebug)
4850 if (cl_locs_show.integer)
4853 if (r_timereport_active)
4854 R_TimeReport("showlocs");
4857 if (r_drawportals.integer)
4860 if (r_timereport_active)
4861 R_TimeReport("portals");
4864 if (r_showbboxes.value > 0)
4866 R_DrawEntityBBoxes();
4867 if (r_timereport_active)
4868 R_TimeReport("bboxes");
4872 R_SetupGenericShader(true);
4873 R_MeshQueue_RenderTransparent();
4874 if (r_timereport_active)
4875 R_TimeReport("drawtrans");
4877 R_SetupGenericShader(true);
4879 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))
4881 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4882 if (r_timereport_active)
4883 R_TimeReport("worlddebug");
4884 R_DrawModelsDebug();
4885 if (r_timereport_active)
4886 R_TimeReport("modeldebug");
4889 R_SetupGenericShader(true);
4891 if (cl.csqc_vidvars.drawworld)
4894 if (r_timereport_active)
4895 R_TimeReport("coronas");
4898 // don't let sound skip if going slow
4899 if (r_refdef.scene.extraupdate)
4902 R_ResetViewRendering2D();
4905 static const unsigned short bboxelements[36] =
4915 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4918 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4919 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4920 GL_DepthMask(false);
4921 GL_DepthRange(0, 1);
4922 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4923 R_Mesh_Matrix(&identitymatrix);
4924 R_Mesh_ResetTextureState();
4926 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
4927 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
4929 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4930 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4931 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4932 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4933 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4934 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4935 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4936 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4937 R_FillColors(color4f, 8, cr, cg, cb, ca);
4938 if (r_refdef.fogenabled)
4940 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4942 f1 = RSurf_FogVertex(v);
4944 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4945 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4946 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4949 R_Mesh_VertexPointer(vertex3f, 0, 0);
4950 R_Mesh_ColorPointer(color4f, 0, 0);
4951 R_Mesh_ResetTextureState();
4952 R_SetupGenericShader(false);
4953 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4956 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4960 prvm_edict_t *edict;
4961 prvm_prog_t *prog_save = prog;
4963 // this function draws bounding boxes of server entities
4967 GL_CullFace(GL_NONE);
4968 R_SetupGenericShader(false);
4972 for (i = 0;i < numsurfaces;i++)
4974 edict = PRVM_EDICT_NUM(surfacelist[i]);
4975 switch ((int)edict->fields.server->solid)
4977 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4978 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4979 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4980 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4981 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4982 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4984 color[3] *= r_showbboxes.value;
4985 color[3] = bound(0, color[3], 1);
4986 GL_DepthTest(!r_showdisabledepthtest.integer);
4987 GL_CullFace(r_refdef.view.cullface_front);
4988 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4994 static void R_DrawEntityBBoxes(void)
4997 prvm_edict_t *edict;
4999 prvm_prog_t *prog_save = prog;
5001 // this function draws bounding boxes of server entities
5007 for (i = 0;i < prog->num_edicts;i++)
5009 edict = PRVM_EDICT_NUM(i);
5010 if (edict->priv.server->free)
5012 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5013 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5015 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5017 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5018 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5024 unsigned short nomodelelements[24] =
5036 float nomodelvertex3f[6*3] =
5046 float nomodelcolor4f[6*4] =
5048 0.0f, 0.0f, 0.5f, 1.0f,
5049 0.0f, 0.0f, 0.5f, 1.0f,
5050 0.0f, 0.5f, 0.0f, 1.0f,
5051 0.0f, 0.5f, 0.0f, 1.0f,
5052 0.5f, 0.0f, 0.0f, 1.0f,
5053 0.5f, 0.0f, 0.0f, 1.0f
5056 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5062 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5063 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5065 // this is only called once per entity so numsurfaces is always 1, and
5066 // surfacelist is always {0}, so this code does not handle batches
5067 R_Mesh_Matrix(&ent->matrix);
5069 if (ent->flags & EF_ADDITIVE)
5071 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5072 GL_DepthMask(false);
5074 else if (ent->alpha < 1)
5076 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5077 GL_DepthMask(false);
5081 GL_BlendFunc(GL_ONE, GL_ZERO);
5084 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5085 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5086 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
5087 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5088 R_SetupGenericShader(false);
5089 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
5090 if (r_refdef.fogenabled)
5093 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5094 R_Mesh_ColorPointer(color4f, 0, 0);
5095 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5096 f1 = RSurf_FogVertex(org);
5098 for (i = 0, c = color4f;i < 6;i++, c += 4)
5100 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5101 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5102 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5106 else if (ent->alpha != 1)
5108 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5109 R_Mesh_ColorPointer(color4f, 0, 0);
5110 for (i = 0, c = color4f;i < 6;i++, c += 4)
5114 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
5115 R_Mesh_ResetTextureState();
5116 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
5119 void R_DrawNoModel(entity_render_t *ent)
5122 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5123 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
5124 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5126 // R_DrawNoModelCallback(ent, 0);
5129 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5131 vec3_t right1, right2, diff, normal;
5133 VectorSubtract (org2, org1, normal);
5135 // calculate 'right' vector for start
5136 VectorSubtract (r_refdef.view.origin, org1, diff);
5137 CrossProduct (normal, diff, right1);
5138 VectorNormalize (right1);
5140 // calculate 'right' vector for end
5141 VectorSubtract (r_refdef.view.origin, org2, diff);
5142 CrossProduct (normal, diff, right2);
5143 VectorNormalize (right2);
5145 vert[ 0] = org1[0] + width * right1[0];
5146 vert[ 1] = org1[1] + width * right1[1];
5147 vert[ 2] = org1[2] + width * right1[2];
5148 vert[ 3] = org1[0] - width * right1[0];
5149 vert[ 4] = org1[1] - width * right1[1];
5150 vert[ 5] = org1[2] - width * right1[2];
5151 vert[ 6] = org2[0] - width * right2[0];
5152 vert[ 7] = org2[1] - width * right2[1];
5153 vert[ 8] = org2[2] - width * right2[2];
5154 vert[ 9] = org2[0] + width * right2[0];
5155 vert[10] = org2[1] + width * right2[1];
5156 vert[11] = org2[2] + width * right2[2];
5159 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5161 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)
5163 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
5167 // set up global fogging in worldspace (RSurf_FogVertex depends on this)
5168 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5170 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
5171 fog = RSurf_FogVertex(origin);
5173 R_Mesh_Matrix(&identitymatrix);
5174 GL_BlendFunc(blendfunc1, blendfunc2);
5176 GL_CullFace(GL_NONE);
5178 GL_DepthMask(false);
5179 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5180 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5181 GL_DepthTest(!depthdisable);
5183 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5184 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5185 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5186 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5187 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5188 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5189 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5190 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5191 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5192 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5193 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5194 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5196 R_Mesh_VertexPointer(vertex3f, 0, 0);
5197 R_Mesh_ColorPointer(NULL, 0, 0);
5198 R_Mesh_ResetTextureState();
5199 R_SetupGenericShader(true);
5200 R_Mesh_TexBind(0, R_GetTexture(texture));
5201 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5202 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5203 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5204 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5206 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5208 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5209 GL_BlendFunc(blendfunc1, GL_ONE);
5211 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5212 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5216 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5221 VectorSet(v, x, y, z);
5222 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5223 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5225 if (i == mesh->numvertices)
5227 if (mesh->numvertices < mesh->maxvertices)
5229 VectorCopy(v, vertex3f);
5230 mesh->numvertices++;
5232 return mesh->numvertices;
5238 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5242 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5243 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5244 e = mesh->element3i + mesh->numtriangles * 3;
5245 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5247 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5248 if (mesh->numtriangles < mesh->maxtriangles)
5253 mesh->numtriangles++;
5255 element[1] = element[2];
5259 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5263 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5264 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5265 e = mesh->element3i + mesh->numtriangles * 3;
5266 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5268 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5269 if (mesh->numtriangles < mesh->maxtriangles)
5274 mesh->numtriangles++;
5276 element[1] = element[2];
5280 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5281 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5283 int planenum, planenum2;
5286 mplane_t *plane, *plane2;
5288 double temppoints[2][256*3];
5289 // figure out how large a bounding box we need to properly compute this brush
5291 for (w = 0;w < numplanes;w++)
5292 maxdist = max(maxdist, fabs(planes[w].dist));
5293 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5294 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5295 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5299 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5300 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5302 if (planenum2 == planenum)
5304 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);
5307 if (tempnumpoints < 3)
5309 // generate elements forming a triangle fan for this polygon
5310 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5314 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)
5316 texturelayer_t *layer;
5317 layer = t->currentlayers + t->currentnumlayers++;
5319 layer->depthmask = depthmask;
5320 layer->blendfunc1 = blendfunc1;
5321 layer->blendfunc2 = blendfunc2;
5322 layer->texture = texture;
5323 layer->texmatrix = *matrix;
5324 layer->color[0] = r * r_refdef.view.colorscale;
5325 layer->color[1] = g * r_refdef.view.colorscale;
5326 layer->color[2] = b * r_refdef.view.colorscale;
5327 layer->color[3] = a;
5330 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5333 index = parms[2] + r_refdef.scene.time * parms[3];
5334 index -= floor(index);
5338 case Q3WAVEFUNC_NONE:
5339 case Q3WAVEFUNC_NOISE:
5340 case Q3WAVEFUNC_COUNT:
5343 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5344 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5345 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5346 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5347 case Q3WAVEFUNC_TRIANGLE:
5349 f = index - floor(index);
5360 return (float)(parms[0] + parms[1] * f);
5363 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5368 matrix4x4_t matrix, temp;
5369 switch(tcmod->tcmod)
5373 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5374 matrix = r_waterscrollmatrix;
5376 matrix = identitymatrix;
5378 case Q3TCMOD_ENTITYTRANSLATE:
5379 // this is used in Q3 to allow the gamecode to control texcoord
5380 // scrolling on the entity, which is not supported in darkplaces yet.
5381 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5383 case Q3TCMOD_ROTATE:
5384 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5385 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5386 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5389 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5391 case Q3TCMOD_SCROLL:
5392 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5394 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5395 w = (int) tcmod->parms[0];
5396 h = (int) tcmod->parms[1];
5397 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5399 idx = (int) floor(f * w * h);
5400 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5402 case Q3TCMOD_STRETCH:
5403 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5404 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5406 case Q3TCMOD_TRANSFORM:
5407 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5408 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5409 VectorSet(tcmat + 6, 0 , 0 , 1);
5410 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5411 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5413 case Q3TCMOD_TURBULENT:
5414 // this is handled in the RSurf_PrepareVertices function
5415 matrix = identitymatrix;
5419 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5422 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5424 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5425 char name[MAX_QPATH];
5426 skinframe_t *skinframe;
5427 unsigned char pixels[296*194];
5428 strlcpy(cache->name, skinname, sizeof(cache->name));
5429 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5430 if (developer_loading.integer)
5431 Con_Printf("loading %s\n", name);
5432 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5433 if (!skinframe || !skinframe->base)
5436 fs_offset_t filesize;
5438 f = FS_LoadFile(name, tempmempool, true, &filesize);
5441 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5442 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5446 cache->skinframe = skinframe;
5449 texture_t *R_GetCurrentTexture(texture_t *t)
5452 const entity_render_t *ent = rsurface.entity;
5453 dp_model_t *model = ent->model;
5454 q3shaderinfo_layer_tcmod_t *tcmod;
5456 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5457 return t->currentframe;
5458 t->update_lastrenderframe = r_frame;
5459 t->update_lastrenderentity = (void *)ent;
5461 // switch to an alternate material if this is a q1bsp animated material
5463 texture_t *texture = t;
5464 int s = ent->skinnum;
5465 if ((unsigned int)s >= (unsigned int)model->numskins)
5467 if (model->skinscenes)
5469 if (model->skinscenes[s].framecount > 1)
5470 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5472 s = model->skinscenes[s].firstframe;
5475 t = t + s * model->num_surfaces;
5478 // use an alternate animation if the entity's frame is not 0,
5479 // and only if the texture has an alternate animation
5480 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
5481 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5483 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5485 texture->currentframe = t;
5488 // update currentskinframe to be a qw skin or animation frame
5489 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"))
5491 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5493 r_qwskincache_size = cl.maxclients;
5495 Mem_Free(r_qwskincache);
5496 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5498 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5499 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5500 t->currentskinframe = r_qwskincache[i].skinframe;
5501 if (t->currentskinframe == NULL)
5502 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5504 else if (t->numskinframes >= 2)
5505 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5506 if (t->backgroundnumskinframes >= 2)
5507 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
5509 t->currentmaterialflags = t->basematerialflags;
5510 t->currentalpha = ent->alpha;
5511 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5512 t->currentalpha *= r_wateralpha.value;
5513 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5514 t->currentalpha *= t->r_water_wateralpha;
5515 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5516 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5517 if (!(ent->flags & RENDER_LIGHT))
5518 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5519 else if (rsurface.modeltexcoordlightmap2f == NULL)
5521 // pick a model lighting mode
5522 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5523 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5525 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5527 if (ent->effects & EF_ADDITIVE)
5528 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5529 else if (t->currentalpha < 1)
5530 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5531 if (ent->effects & EF_DOUBLESIDED)
5532 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5533 if (ent->effects & EF_NODEPTHTEST)
5534 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5535 if (ent->flags & RENDER_VIEWMODEL)
5536 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5537 if (t->backgroundnumskinframes)
5538 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5539 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5541 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5542 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5545 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5547 // there is no tcmod
5548 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5550 t->currenttexmatrix = r_waterscrollmatrix;
5551 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5555 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5556 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5559 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5560 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5561 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5562 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5564 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5565 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5566 t->glosstexture = r_texture_black;
5567 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5568 t->backgroundglosstexture = r_texture_black;
5569 t->specularpower = r_shadow_glossexponent.value;
5570 // TODO: store reference values for these in the texture?
5571 t->specularscale = 0;
5572 if (r_shadow_gloss.integer > 0)
5574 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5576 if (r_shadow_glossintensity.value > 0)
5578 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5579 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5580 t->specularscale = r_shadow_glossintensity.value;
5583 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5585 t->glosstexture = r_texture_white;
5586 t->backgroundglosstexture = r_texture_white;
5587 t->specularscale = r_shadow_gloss2intensity.value;
5588 t->specularpower = r_shadow_gloss2exponent.value;
5591 t->specularscale *= t->specularscalemod;
5592 t->specularpower *= t->specularpowermod;
5594 // lightmaps mode looks bad with dlights using actual texturing, so turn
5595 // off the colormap and glossmap, but leave the normalmap on as it still
5596 // accurately represents the shading involved
5597 if (gl_lightmaps.integer)
5599 t->basetexture = r_texture_grey128;
5600 t->backgroundbasetexture = NULL;
5601 t->specularscale = 0;
5602 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5605 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5606 VectorClear(t->dlightcolor);
5607 t->currentnumlayers = 0;
5608 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5611 int blendfunc1, blendfunc2;
5613 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5615 blendfunc1 = GL_SRC_ALPHA;
5616 blendfunc2 = GL_ONE;
5618 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5620 blendfunc1 = GL_SRC_ALPHA;
5621 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5623 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5625 blendfunc1 = t->customblendfunc[0];
5626 blendfunc2 = t->customblendfunc[1];
5630 blendfunc1 = GL_ONE;
5631 blendfunc2 = GL_ZERO;
5633 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5634 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5635 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5636 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5638 // fullbright is not affected by r_refdef.lightmapintensity
5639 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]);
5640 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5641 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]);
5642 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5643 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]);
5647 vec3_t ambientcolor;
5649 // set the color tint used for lights affecting this surface
5650 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5652 // q3bsp has no lightmap updates, so the lightstylevalue that
5653 // would normally be baked into the lightmap must be
5654 // applied to the color
5655 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5656 if (ent->model->type == mod_brushq3)
5657 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5658 colorscale *= r_refdef.lightmapintensity;
5659 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5660 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5661 // basic lit geometry
5662 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]);
5663 // add pants/shirt if needed
5664 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5665 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]);
5666 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5667 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]);
5668 // now add ambient passes if needed
5669 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5671 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]);
5672 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5673 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]);
5674 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5675 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]);
5678 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5679 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]);
5680 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5682 // if this is opaque use alpha blend which will darken the earlier
5685 // if this is an alpha blended material, all the earlier passes
5686 // were darkened by fog already, so we only need to add the fog
5687 // color ontop through the fog mask texture
5689 // if this is an additive blended material, all the earlier passes
5690 // were darkened by fog already, and we should not add fog color
5691 // (because the background was not darkened, there is no fog color
5692 // that was lost behind it).
5693 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]);
5697 return t->currentframe;
5700 rsurfacestate_t rsurface;
5702 void R_Mesh_ResizeArrays(int newvertices)
5705 if (rsurface.array_size >= newvertices)
5707 if (rsurface.array_modelvertex3f)
5708 Mem_Free(rsurface.array_modelvertex3f);
5709 rsurface.array_size = (newvertices + 1023) & ~1023;
5710 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5711 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5712 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5713 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5714 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5715 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5716 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5717 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5718 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5719 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5720 rsurface.array_color4f = base + rsurface.array_size * 27;
5721 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5724 void RSurf_ActiveWorldEntity(void)
5726 dp_model_t *model = r_refdef.scene.worldmodel;
5727 //if (rsurface.entity == r_refdef.scene.worldentity)
5729 rsurface.entity = r_refdef.scene.worldentity;
5730 if (rsurface.array_size < model->surfmesh.num_vertices)
5731 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5732 rsurface.matrix = identitymatrix;
5733 rsurface.inversematrix = identitymatrix;
5734 R_Mesh_Matrix(&identitymatrix);
5735 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
5736 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5737 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5738 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5739 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5740 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5741 VectorSet(rsurface.glowmod, 1, 1, 1);
5742 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5743 rsurface.frameblend[0].lerp = 1;
5744 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5745 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5746 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5747 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5748 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5749 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5750 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5751 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5752 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5753 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5754 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5755 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5756 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5757 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5758 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5759 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5760 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5761 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5762 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5763 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5764 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5765 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5766 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5767 rsurface.modelelement3i = model->surfmesh.data_element3i;
5768 rsurface.modelelement3s = model->surfmesh.data_element3s;
5769 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5770 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5771 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5772 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5773 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5774 rsurface.modelsurfaces = model->data_surfaces;
5775 rsurface.generatedvertex = false;
5776 rsurface.vertex3f = rsurface.modelvertex3f;
5777 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5778 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5779 rsurface.svector3f = rsurface.modelsvector3f;
5780 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5781 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5782 rsurface.tvector3f = rsurface.modeltvector3f;
5783 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5784 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5785 rsurface.normal3f = rsurface.modelnormal3f;
5786 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5787 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5788 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5791 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5793 dp_model_t *model = ent->model;
5794 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5796 rsurface.entity = (entity_render_t *)ent;
5797 if (rsurface.array_size < model->surfmesh.num_vertices)
5798 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5799 rsurface.matrix = ent->matrix;
5800 rsurface.inversematrix = ent->inversematrix;
5801 R_Mesh_Matrix(&rsurface.matrix);
5802 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
5803 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5804 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5805 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5806 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5807 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5808 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5809 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5810 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5811 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5812 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5813 VectorCopy(ent->glowmod, rsurface.glowmod);
5814 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5815 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5816 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5817 if (ent->model->brush.submodel)
5819 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5820 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5822 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5824 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5826 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5827 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5828 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5829 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5831 else if (wanttangents)
5833 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5834 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5835 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5836 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5837 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5839 else if (wantnormals)
5841 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5842 rsurface.modelsvector3f = NULL;
5843 rsurface.modeltvector3f = NULL;
5844 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5845 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5849 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5850 rsurface.modelsvector3f = NULL;
5851 rsurface.modeltvector3f = NULL;
5852 rsurface.modelnormal3f = NULL;
5853 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5855 rsurface.modelvertex3f_bufferobject = 0;
5856 rsurface.modelvertex3f_bufferoffset = 0;
5857 rsurface.modelsvector3f_bufferobject = 0;
5858 rsurface.modelsvector3f_bufferoffset = 0;
5859 rsurface.modeltvector3f_bufferobject = 0;
5860 rsurface.modeltvector3f_bufferoffset = 0;
5861 rsurface.modelnormal3f_bufferobject = 0;
5862 rsurface.modelnormal3f_bufferoffset = 0;
5863 rsurface.generatedvertex = true;
5867 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5868 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5869 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5870 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5871 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5872 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5873 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5874 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5875 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5876 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5877 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5878 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5879 rsurface.generatedvertex = false;
5881 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5882 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5883 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5884 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5885 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5886 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5887 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5888 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5889 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5890 rsurface.modelelement3i = model->surfmesh.data_element3i;
5891 rsurface.modelelement3s = model->surfmesh.data_element3s;
5892 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5893 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5894 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5895 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5896 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5897 rsurface.modelsurfaces = model->data_surfaces;
5898 rsurface.vertex3f = rsurface.modelvertex3f;
5899 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5900 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5901 rsurface.svector3f = rsurface.modelsvector3f;
5902 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5903 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5904 rsurface.tvector3f = rsurface.modeltvector3f;
5905 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5906 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5907 rsurface.normal3f = rsurface.modelnormal3f;
5908 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5909 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5910 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5913 float RSurf_FogVertex(const float *v)
5915 float len = VectorDistance(rsurface.localvieworigin, v);
5916 unsigned int fogmasktableindex;
5917 fogmasktableindex = (unsigned int)(len * r_refdef.fogmasktabledistmultiplier);
5918 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
5921 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5922 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5925 int texturesurfaceindex;
5930 const float *v1, *in_tc;
5932 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5934 q3shaderinfo_deform_t *deform;
5935 // 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
5936 if (rsurface.generatedvertex)
5938 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5939 generatenormals = true;
5940 for (i = 0;i < Q3MAXDEFORMS;i++)
5942 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5944 generatetangents = true;
5945 generatenormals = true;
5947 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5948 generatenormals = true;
5950 if (generatenormals && !rsurface.modelnormal3f)
5952 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5953 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5954 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5955 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
5957 if (generatetangents && !rsurface.modelsvector3f)
5959 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5960 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5961 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5962 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5963 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5964 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5965 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);
5968 rsurface.vertex3f = rsurface.modelvertex3f;
5969 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5970 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5971 rsurface.svector3f = rsurface.modelsvector3f;
5972 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5973 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5974 rsurface.tvector3f = rsurface.modeltvector3f;
5975 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5976 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5977 rsurface.normal3f = rsurface.modelnormal3f;
5978 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5979 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5980 // if vertices are deformed (sprite flares and things in maps, possibly
5981 // water waves, bulges and other deformations), generate them into
5982 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5983 // (may be static model data or generated data for an animated model, or
5984 // the previous deform pass)
5985 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5987 switch (deform->deform)
5990 case Q3DEFORM_PROJECTIONSHADOW:
5991 case Q3DEFORM_TEXT0:
5992 case Q3DEFORM_TEXT1:
5993 case Q3DEFORM_TEXT2:
5994 case Q3DEFORM_TEXT3:
5995 case Q3DEFORM_TEXT4:
5996 case Q3DEFORM_TEXT5:
5997 case Q3DEFORM_TEXT6:
5998 case Q3DEFORM_TEXT7:
6001 case Q3DEFORM_AUTOSPRITE:
6002 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6003 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6004 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6005 VectorNormalize(newforward);
6006 VectorNormalize(newright);
6007 VectorNormalize(newup);
6008 // make deformed versions of only the model vertices used by the specified surfaces
6009 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6011 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6012 // a single autosprite surface can contain multiple sprites...
6013 for (j = 0;j < surface->num_vertices - 3;j += 4)
6015 VectorClear(center);
6016 for (i = 0;i < 4;i++)
6017 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6018 VectorScale(center, 0.25f, center);
6019 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6020 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6021 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6022 for (i = 0;i < 4;i++)
6024 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6025 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6028 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);
6029 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);
6031 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6032 rsurface.vertex3f_bufferobject = 0;
6033 rsurface.vertex3f_bufferoffset = 0;
6034 rsurface.svector3f = rsurface.array_deformedsvector3f;
6035 rsurface.svector3f_bufferobject = 0;
6036 rsurface.svector3f_bufferoffset = 0;
6037 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6038 rsurface.tvector3f_bufferobject = 0;
6039 rsurface.tvector3f_bufferoffset = 0;
6040 rsurface.normal3f = rsurface.array_deformednormal3f;
6041 rsurface.normal3f_bufferobject = 0;
6042 rsurface.normal3f_bufferoffset = 0;
6044 case Q3DEFORM_AUTOSPRITE2:
6045 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6046 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6047 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6048 VectorNormalize(newforward);
6049 VectorNormalize(newright);
6050 VectorNormalize(newup);
6051 // make deformed versions of only the model vertices used by the specified surfaces
6052 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6054 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6055 const float *v1, *v2;
6065 memset(shortest, 0, sizeof(shortest));
6066 // a single autosprite surface can contain multiple sprites...
6067 for (j = 0;j < surface->num_vertices - 3;j += 4)
6069 VectorClear(center);
6070 for (i = 0;i < 4;i++)
6071 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6072 VectorScale(center, 0.25f, center);
6073 // find the two shortest edges, then use them to define the
6074 // axis vectors for rotating around the central axis
6075 for (i = 0;i < 6;i++)
6077 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6078 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6080 Debug_PolygonBegin(NULL, 0);
6081 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6082 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);
6083 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6086 l = VectorDistance2(v1, v2);
6087 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6089 l += (1.0f / 1024.0f);
6090 if (shortest[0].length2 > l || i == 0)
6092 shortest[1] = shortest[0];
6093 shortest[0].length2 = l;
6094 shortest[0].v1 = v1;
6095 shortest[0].v2 = v2;
6097 else if (shortest[1].length2 > l || i == 1)
6099 shortest[1].length2 = l;
6100 shortest[1].v1 = v1;
6101 shortest[1].v2 = v2;
6104 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6105 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6107 Debug_PolygonBegin(NULL, 0);
6108 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6109 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);
6110 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6113 // this calculates the right vector from the shortest edge
6114 // and the up vector from the edge midpoints
6115 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6116 VectorNormalize(right);
6117 VectorSubtract(end, start, up);
6118 VectorNormalize(up);
6119 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6120 VectorSubtract(rsurface.localvieworigin, center, forward);
6121 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6122 VectorNegate(forward, forward);
6123 VectorReflect(forward, 0, up, forward);
6124 VectorNormalize(forward);
6125 CrossProduct(up, forward, newright);
6126 VectorNormalize(newright);
6128 Debug_PolygonBegin(NULL, 0);
6129 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);
6130 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6131 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6135 Debug_PolygonBegin(NULL, 0);
6136 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6137 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6138 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6141 // rotate the quad around the up axis vector, this is made
6142 // especially easy by the fact we know the quad is flat,
6143 // so we only have to subtract the center position and
6144 // measure distance along the right vector, and then
6145 // multiply that by the newright vector and add back the
6147 // we also need to subtract the old position to undo the
6148 // displacement from the center, which we do with a
6149 // DotProduct, the subtraction/addition of center is also
6150 // optimized into DotProducts here
6151 l = DotProduct(right, center);
6152 for (i = 0;i < 4;i++)
6154 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6155 f = DotProduct(right, v1) - l;
6156 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6159 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);
6160 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);
6162 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6163 rsurface.vertex3f_bufferobject = 0;
6164 rsurface.vertex3f_bufferoffset = 0;
6165 rsurface.svector3f = rsurface.array_deformedsvector3f;
6166 rsurface.svector3f_bufferobject = 0;
6167 rsurface.svector3f_bufferoffset = 0;
6168 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6169 rsurface.tvector3f_bufferobject = 0;
6170 rsurface.tvector3f_bufferoffset = 0;
6171 rsurface.normal3f = rsurface.array_deformednormal3f;
6172 rsurface.normal3f_bufferobject = 0;
6173 rsurface.normal3f_bufferoffset = 0;
6175 case Q3DEFORM_NORMAL:
6176 // deform the normals to make reflections wavey
6177 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6179 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6180 for (j = 0;j < surface->num_vertices;j++)
6183 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6184 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6185 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6186 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6187 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6188 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6189 VectorNormalize(normal);
6191 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);
6193 rsurface.svector3f = rsurface.array_deformedsvector3f;
6194 rsurface.svector3f_bufferobject = 0;
6195 rsurface.svector3f_bufferoffset = 0;
6196 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6197 rsurface.tvector3f_bufferobject = 0;
6198 rsurface.tvector3f_bufferoffset = 0;
6199 rsurface.normal3f = rsurface.array_deformednormal3f;
6200 rsurface.normal3f_bufferobject = 0;
6201 rsurface.normal3f_bufferoffset = 0;
6204 // deform vertex array to make wavey water and flags and such
6205 waveparms[0] = deform->waveparms[0];
6206 waveparms[1] = deform->waveparms[1];
6207 waveparms[2] = deform->waveparms[2];
6208 waveparms[3] = deform->waveparms[3];
6209 // this is how a divisor of vertex influence on deformation
6210 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6211 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6212 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6214 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6215 for (j = 0;j < surface->num_vertices;j++)
6217 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6218 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6219 // if the wavefunc depends on time, evaluate it per-vertex
6222 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6223 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6225 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6228 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6229 rsurface.vertex3f_bufferobject = 0;
6230 rsurface.vertex3f_bufferoffset = 0;
6232 case Q3DEFORM_BULGE:
6233 // deform vertex array to make the surface have moving bulges
6234 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6236 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6237 for (j = 0;j < surface->num_vertices;j++)
6239 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6240 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6243 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6244 rsurface.vertex3f_bufferobject = 0;
6245 rsurface.vertex3f_bufferoffset = 0;
6248 // deform vertex array
6249 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6250 VectorScale(deform->parms, scale, waveparms);
6251 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6253 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6254 for (j = 0;j < surface->num_vertices;j++)
6255 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6257 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6258 rsurface.vertex3f_bufferobject = 0;
6259 rsurface.vertex3f_bufferoffset = 0;
6263 // generate texcoords based on the chosen texcoord source
6264 switch(rsurface.texture->tcgen.tcgen)
6267 case Q3TCGEN_TEXTURE:
6268 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6269 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6270 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6272 case Q3TCGEN_LIGHTMAP:
6273 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6274 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6275 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6277 case Q3TCGEN_VECTOR:
6278 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6280 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6281 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)
6283 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6284 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6287 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6288 rsurface.texcoordtexture2f_bufferobject = 0;
6289 rsurface.texcoordtexture2f_bufferoffset = 0;
6291 case Q3TCGEN_ENVIRONMENT:
6292 // make environment reflections using a spheremap
6293 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6295 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6296 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6297 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6298 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6299 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6301 // identical to Q3A's method, but executed in worldspace so
6302 // carried models can be shiny too
6304 float viewer[3], d, reflected[3], worldreflected[3];
6306 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6307 // VectorNormalize(viewer);
6309 d = DotProduct(normal, viewer);
6311 reflected[0] = normal[0]*2*d - viewer[0];
6312 reflected[1] = normal[1]*2*d - viewer[1];
6313 reflected[2] = normal[2]*2*d - viewer[2];
6314 // note: this is proportinal to viewer, so we can normalize later
6316 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6317 VectorNormalize(worldreflected);
6319 // note: this sphere map only uses world x and z!
6320 // so positive and negative y will LOOK THE SAME.
6321 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6322 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6325 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6326 rsurface.texcoordtexture2f_bufferobject = 0;
6327 rsurface.texcoordtexture2f_bufferoffset = 0;
6330 // the only tcmod that needs software vertex processing is turbulent, so
6331 // check for it here and apply the changes if needed
6332 // and we only support that as the first one
6333 // (handling a mixture of turbulent and other tcmods would be problematic
6334 // without punting it entirely to a software path)
6335 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6337 amplitude = rsurface.texture->tcmods[0].parms[1];
6338 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6339 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6341 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6342 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)
6344 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6345 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6348 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6349 rsurface.texcoordtexture2f_bufferobject = 0;
6350 rsurface.texcoordtexture2f_bufferoffset = 0;
6352 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6353 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6354 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6355 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6358 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6361 const msurface_t *surface = texturesurfacelist[0];
6362 const msurface_t *surface2;
6367 // TODO: lock all array ranges before render, rather than on each surface
6368 if (texturenumsurfaces == 1)
6370 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6371 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);
6373 else if (r_batchmode.integer == 2)
6375 #define MAXBATCHTRIANGLES 4096
6376 int batchtriangles = 0;
6377 int batchelements[MAXBATCHTRIANGLES*3];
6378 for (i = 0;i < texturenumsurfaces;i = j)
6380 surface = texturesurfacelist[i];
6382 if (surface->num_triangles > MAXBATCHTRIANGLES)
6384 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);
6387 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6388 batchtriangles = surface->num_triangles;
6389 firstvertex = surface->num_firstvertex;
6390 endvertex = surface->num_firstvertex + surface->num_vertices;
6391 for (;j < texturenumsurfaces;j++)
6393 surface2 = texturesurfacelist[j];
6394 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6396 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6397 batchtriangles += surface2->num_triangles;
6398 firstvertex = min(firstvertex, surface2->num_firstvertex);
6399 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6401 surface2 = texturesurfacelist[j-1];
6402 numvertices = endvertex - firstvertex;
6403 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6406 else if (r_batchmode.integer == 1)
6408 for (i = 0;i < texturenumsurfaces;i = j)
6410 surface = texturesurfacelist[i];
6411 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6412 if (texturesurfacelist[j] != surface2)
6414 surface2 = texturesurfacelist[j-1];
6415 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6416 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6417 GL_LockArrays(surface->num_firstvertex, numvertices);
6418 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6423 for (i = 0;i < texturenumsurfaces;i++)
6425 surface = texturesurfacelist[i];
6426 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6427 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);
6432 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6434 int i, planeindex, vertexindex;
6438 r_waterstate_waterplane_t *p, *bestp;
6439 msurface_t *surface;
6440 if (r_waterstate.renderingscene)
6442 for (i = 0;i < texturenumsurfaces;i++)
6444 surface = texturesurfacelist[i];
6445 if (lightmaptexunit >= 0)
6446 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6447 if (deluxemaptexunit >= 0)
6448 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6449 // pick the closest matching water plane
6452 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6455 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6457 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6458 d += fabs(PlaneDiff(vert, &p->plane));
6460 if (bestd > d || !bestp)
6468 if (refractiontexunit >= 0)
6469 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6470 if (reflectiontexunit >= 0)
6471 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6475 if (refractiontexunit >= 0)
6476 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6477 if (reflectiontexunit >= 0)
6478 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6480 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6481 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);
6485 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6489 const msurface_t *surface = texturesurfacelist[0];
6490 const msurface_t *surface2;
6495 // TODO: lock all array ranges before render, rather than on each surface
6496 if (texturenumsurfaces == 1)
6498 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6499 if (deluxemaptexunit >= 0)
6500 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6501 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6502 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);
6504 else if (r_batchmode.integer == 2)
6506 #define MAXBATCHTRIANGLES 4096
6507 int batchtriangles = 0;
6508 int batchelements[MAXBATCHTRIANGLES*3];
6509 for (i = 0;i < texturenumsurfaces;i = j)
6511 surface = texturesurfacelist[i];
6512 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6513 if (deluxemaptexunit >= 0)
6514 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6516 if (surface->num_triangles > MAXBATCHTRIANGLES)
6518 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);
6521 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6522 batchtriangles = surface->num_triangles;
6523 firstvertex = surface->num_firstvertex;
6524 endvertex = surface->num_firstvertex + surface->num_vertices;
6525 for (;j < texturenumsurfaces;j++)
6527 surface2 = texturesurfacelist[j];
6528 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6530 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6531 batchtriangles += surface2->num_triangles;
6532 firstvertex = min(firstvertex, surface2->num_firstvertex);
6533 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6535 surface2 = texturesurfacelist[j-1];
6536 numvertices = endvertex - firstvertex;
6537 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6540 else if (r_batchmode.integer == 1)
6543 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6544 for (i = 0;i < texturenumsurfaces;i = j)
6546 surface = texturesurfacelist[i];
6547 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6548 if (texturesurfacelist[j] != surface2)
6550 Con_Printf(" %i", j - i);
6553 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6555 for (i = 0;i < texturenumsurfaces;i = j)
6557 surface = texturesurfacelist[i];
6558 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6559 if (deluxemaptexunit >= 0)
6560 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6561 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6562 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6565 Con_Printf(" %i", j - i);
6567 surface2 = texturesurfacelist[j-1];
6568 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6569 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6570 GL_LockArrays(surface->num_firstvertex, numvertices);
6571 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6579 for (i = 0;i < texturenumsurfaces;i++)
6581 surface = texturesurfacelist[i];
6582 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6583 if (deluxemaptexunit >= 0)
6584 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6585 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6586 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);
6591 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6594 int texturesurfaceindex;
6595 if (r_showsurfaces.integer == 2)
6597 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6599 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6600 for (j = 0;j < surface->num_triangles;j++)
6602 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6603 GL_Color(f, f, f, 1);
6604 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6610 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6612 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6613 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6614 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);
6615 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6616 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);
6621 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6623 int texturesurfaceindex;
6626 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6628 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6629 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)
6637 rsurface.lightmapcolor4f = rsurface.array_color4f;
6638 rsurface.lightmapcolor4f_bufferobject = 0;
6639 rsurface.lightmapcolor4f_bufferoffset = 0;
6642 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6644 int texturesurfaceindex;
6648 if (rsurface.lightmapcolor4f)
6650 // generate color arrays for the surfaces in this list
6651 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6653 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6654 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)
6656 f = RSurf_FogVertex(v);
6666 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6668 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6669 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)
6671 f = RSurf_FogVertex(v);
6679 rsurface.lightmapcolor4f = rsurface.array_color4f;
6680 rsurface.lightmapcolor4f_bufferobject = 0;
6681 rsurface.lightmapcolor4f_bufferoffset = 0;
6684 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6686 int texturesurfaceindex;
6690 if (!rsurface.lightmapcolor4f)
6692 // generate color arrays for the surfaces in this list
6693 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6695 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6696 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)
6698 f = RSurf_FogVertex(v);
6699 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6700 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6701 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6705 rsurface.lightmapcolor4f = rsurface.array_color4f;
6706 rsurface.lightmapcolor4f_bufferobject = 0;
6707 rsurface.lightmapcolor4f_bufferoffset = 0;
6710 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6712 int texturesurfaceindex;
6715 if (!rsurface.lightmapcolor4f)
6717 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6719 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6720 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)
6728 rsurface.lightmapcolor4f = rsurface.array_color4f;
6729 rsurface.lightmapcolor4f_bufferobject = 0;
6730 rsurface.lightmapcolor4f_bufferoffset = 0;
6733 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6735 int texturesurfaceindex;
6738 if (!rsurface.lightmapcolor4f)
6740 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6742 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6743 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)
6745 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6746 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6747 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6751 rsurface.lightmapcolor4f = rsurface.array_color4f;
6752 rsurface.lightmapcolor4f_bufferobject = 0;
6753 rsurface.lightmapcolor4f_bufferoffset = 0;
6756 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6759 rsurface.lightmapcolor4f = NULL;
6760 rsurface.lightmapcolor4f_bufferobject = 0;
6761 rsurface.lightmapcolor4f_bufferoffset = 0;
6762 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6763 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6764 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6765 GL_Color(r, g, b, a);
6766 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6769 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6771 // TODO: optimize applyfog && applycolor case
6772 // just apply fog if necessary, and tint the fog color array if necessary
6773 rsurface.lightmapcolor4f = NULL;
6774 rsurface.lightmapcolor4f_bufferobject = 0;
6775 rsurface.lightmapcolor4f_bufferoffset = 0;
6776 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6777 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6778 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6779 GL_Color(r, g, b, a);
6780 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6783 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6785 int texturesurfaceindex;
6789 if (texturesurfacelist[0]->lightmapinfo)
6791 // generate color arrays for the surfaces in this list
6792 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6794 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6795 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6797 if (surface->lightmapinfo->samples)
6799 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6800 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6801 VectorScale(lm, scale, c);
6802 if (surface->lightmapinfo->styles[1] != 255)
6804 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6806 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6807 VectorMA(c, scale, lm, c);
6808 if (surface->lightmapinfo->styles[2] != 255)
6811 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6812 VectorMA(c, scale, lm, c);
6813 if (surface->lightmapinfo->styles[3] != 255)
6816 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6817 VectorMA(c, scale, lm, c);
6827 rsurface.lightmapcolor4f = rsurface.array_color4f;
6828 rsurface.lightmapcolor4f_bufferobject = 0;
6829 rsurface.lightmapcolor4f_bufferoffset = 0;
6833 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6834 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6835 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6837 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6838 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6839 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6840 GL_Color(r, g, b, a);
6841 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6844 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6846 int texturesurfaceindex;
6849 float *v, *c, *c2, alpha;
6850 vec3_t ambientcolor;
6851 vec3_t diffusecolor;
6855 VectorCopy(rsurface.modellight_lightdir, lightdir);
6856 f = 0.5f * r_refdef.lightmapintensity;
6857 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6858 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6859 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6860 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6861 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6862 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6864 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6866 // generate color arrays for the surfaces in this list
6867 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6869 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6870 int numverts = surface->num_vertices;
6871 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6872 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6873 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6874 // q3-style directional shading
6875 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6877 if ((f = DotProduct(c2, lightdir)) > 0)
6878 VectorMA(ambientcolor, f, diffusecolor, c);
6880 VectorCopy(ambientcolor, c);
6888 rsurface.lightmapcolor4f = rsurface.array_color4f;
6889 rsurface.lightmapcolor4f_bufferobject = 0;
6890 rsurface.lightmapcolor4f_bufferoffset = 0;
6891 *applycolor = false;
6895 *r = ambientcolor[0];
6896 *g = ambientcolor[1];
6897 *b = ambientcolor[2];
6898 rsurface.lightmapcolor4f = NULL;
6899 rsurface.lightmapcolor4f_bufferobject = 0;
6900 rsurface.lightmapcolor4f_bufferoffset = 0;
6904 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6906 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6907 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6908 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6909 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6910 GL_Color(r, g, b, a);
6911 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6914 void RSurf_SetupDepthAndCulling(void)
6916 // submodels are biased to avoid z-fighting with world surfaces that they
6917 // may be exactly overlapping (avoids z-fighting artifacts on certain
6918 // doors and things in Quake maps)
6919 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6920 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6921 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6922 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6925 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6927 // transparent sky would be ridiculous
6928 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6930 R_SetupGenericShader(false);
6933 skyrendernow = false;
6934 // we have to force off the water clipping plane while rendering sky
6938 // restore entity matrix
6939 R_Mesh_Matrix(&rsurface.matrix);
6941 RSurf_SetupDepthAndCulling();
6943 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6944 // skymasking on them, and Quake3 never did sky masking (unlike
6945 // software Quake and software Quake2), so disable the sky masking
6946 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6947 // and skymasking also looks very bad when noclipping outside the
6948 // level, so don't use it then either.
6949 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6951 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6952 R_Mesh_ColorPointer(NULL, 0, 0);
6953 R_Mesh_ResetTextureState();
6954 if (skyrendermasked)
6956 R_SetupDepthOrShadowShader();
6957 // depth-only (masking)
6958 GL_ColorMask(0,0,0,0);
6959 // just to make sure that braindead drivers don't draw
6960 // anything despite that colormask...
6961 GL_BlendFunc(GL_ZERO, GL_ONE);
6965 R_SetupGenericShader(false);
6967 GL_BlendFunc(GL_ONE, GL_ZERO);
6969 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6970 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6971 if (skyrendermasked)
6972 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6974 R_Mesh_ResetTextureState();
6975 GL_Color(1, 1, 1, 1);
6978 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6980 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6983 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6984 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6985 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6986 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6987 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6988 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6989 if (rsurface.texture->backgroundcurrentskinframe)
6991 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6992 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6993 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6994 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6996 if(rsurface.texture->colormapping)
6998 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6999 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7001 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7002 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7003 R_Mesh_ColorPointer(NULL, 0, 0);
7005 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7007 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7009 // render background
7010 GL_BlendFunc(GL_ONE, GL_ZERO);
7012 GL_AlphaTest(false);
7014 GL_Color(1, 1, 1, 1);
7015 R_Mesh_ColorPointer(NULL, 0, 0);
7017 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7018 if (r_glsl_permutation)
7020 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7021 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7022 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7023 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7024 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7025 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7026 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);
7028 GL_LockArrays(0, 0);
7030 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7031 GL_DepthMask(false);
7032 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7033 R_Mesh_ColorPointer(NULL, 0, 0);
7035 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7036 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7037 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7040 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7041 if (!r_glsl_permutation)
7044 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7045 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7046 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7047 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7048 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7049 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7051 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7053 GL_BlendFunc(GL_ONE, GL_ZERO);
7055 GL_AlphaTest(false);
7059 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7060 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7061 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7064 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7066 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7067 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);
7069 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7073 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7074 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);
7076 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7078 GL_LockArrays(0, 0);
7081 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7083 // OpenGL 1.3 path - anything not completely ancient
7084 int texturesurfaceindex;
7085 qboolean applycolor;
7089 const texturelayer_t *layer;
7090 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7092 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7095 int layertexrgbscale;
7096 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7098 if (layerindex == 0)
7102 GL_AlphaTest(false);
7103 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7106 GL_DepthMask(layer->depthmask && writedepth);
7107 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7108 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7110 layertexrgbscale = 4;
7111 VectorScale(layer->color, 0.25f, layercolor);
7113 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7115 layertexrgbscale = 2;
7116 VectorScale(layer->color, 0.5f, layercolor);
7120 layertexrgbscale = 1;
7121 VectorScale(layer->color, 1.0f, layercolor);
7123 layercolor[3] = layer->color[3];
7124 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7125 R_Mesh_ColorPointer(NULL, 0, 0);
7126 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7127 switch (layer->type)
7129 case TEXTURELAYERTYPE_LITTEXTURE:
7130 memset(&m, 0, sizeof(m));
7131 m.tex[0] = R_GetTexture(r_texture_white);
7132 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7133 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7134 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7135 m.tex[1] = R_GetTexture(layer->texture);
7136 m.texmatrix[1] = layer->texmatrix;
7137 m.texrgbscale[1] = layertexrgbscale;
7138 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7139 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7140 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7141 R_Mesh_TextureState(&m);
7142 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7143 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7144 else if (rsurface.uselightmaptexture)
7145 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7147 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7149 case TEXTURELAYERTYPE_TEXTURE:
7150 memset(&m, 0, sizeof(m));
7151 m.tex[0] = R_GetTexture(layer->texture);
7152 m.texmatrix[0] = layer->texmatrix;
7153 m.texrgbscale[0] = layertexrgbscale;
7154 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7155 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7156 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7157 R_Mesh_TextureState(&m);
7158 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7160 case TEXTURELAYERTYPE_FOG:
7161 memset(&m, 0, sizeof(m));
7162 m.texrgbscale[0] = layertexrgbscale;
7165 m.tex[0] = R_GetTexture(layer->texture);
7166 m.texmatrix[0] = layer->texmatrix;
7167 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7168 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7169 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7171 R_Mesh_TextureState(&m);
7172 // generate a color array for the fog pass
7173 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7174 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7178 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7179 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)
7181 f = 1 - RSurf_FogVertex(v);
7182 c[0] = layercolor[0];
7183 c[1] = layercolor[1];
7184 c[2] = layercolor[2];
7185 c[3] = f * layercolor[3];
7188 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7191 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7193 GL_LockArrays(0, 0);
7196 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7198 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7199 GL_AlphaTest(false);
7203 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7205 // OpenGL 1.1 - crusty old voodoo path
7206 int texturesurfaceindex;
7210 const texturelayer_t *layer;
7211 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7213 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7215 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7217 if (layerindex == 0)
7221 GL_AlphaTest(false);
7222 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7225 GL_DepthMask(layer->depthmask && writedepth);
7226 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7227 R_Mesh_ColorPointer(NULL, 0, 0);
7228 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7229 switch (layer->type)
7231 case TEXTURELAYERTYPE_LITTEXTURE:
7232 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7234 // two-pass lit texture with 2x rgbscale
7235 // first the lightmap pass
7236 memset(&m, 0, sizeof(m));
7237 m.tex[0] = R_GetTexture(r_texture_white);
7238 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7239 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7240 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7241 R_Mesh_TextureState(&m);
7242 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7243 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7244 else if (rsurface.uselightmaptexture)
7245 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7247 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7248 GL_LockArrays(0, 0);
7249 // then apply the texture to it
7250 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7251 memset(&m, 0, sizeof(m));
7252 m.tex[0] = R_GetTexture(layer->texture);
7253 m.texmatrix[0] = layer->texmatrix;
7254 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7255 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7256 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7257 R_Mesh_TextureState(&m);
7258 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);
7262 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7263 memset(&m, 0, sizeof(m));
7264 m.tex[0] = R_GetTexture(layer->texture);
7265 m.texmatrix[0] = layer->texmatrix;
7266 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7267 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7268 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7269 R_Mesh_TextureState(&m);
7270 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7271 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);
7273 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);
7276 case TEXTURELAYERTYPE_TEXTURE:
7277 // singletexture unlit texture with transparency support
7278 memset(&m, 0, sizeof(m));
7279 m.tex[0] = R_GetTexture(layer->texture);
7280 m.texmatrix[0] = layer->texmatrix;
7281 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7282 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7283 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7284 R_Mesh_TextureState(&m);
7285 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);
7287 case TEXTURELAYERTYPE_FOG:
7288 // singletexture fogging
7289 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7292 memset(&m, 0, sizeof(m));
7293 m.tex[0] = R_GetTexture(layer->texture);
7294 m.texmatrix[0] = layer->texmatrix;
7295 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7296 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7297 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7298 R_Mesh_TextureState(&m);
7301 R_Mesh_ResetTextureState();
7302 // generate a color array for the fog pass
7303 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7307 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7308 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)
7310 f = 1 - RSurf_FogVertex(v);
7311 c[0] = layer->color[0];
7312 c[1] = layer->color[1];
7313 c[2] = layer->color[2];
7314 c[3] = f * layer->color[3];
7317 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7320 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7322 GL_LockArrays(0, 0);
7325 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7327 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7328 GL_AlphaTest(false);
7332 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7336 GL_AlphaTest(false);
7337 R_Mesh_ColorPointer(NULL, 0, 0);
7338 R_Mesh_ResetTextureState();
7339 R_SetupGenericShader(false);
7341 if(rsurface.texture && rsurface.texture->currentskinframe)
7343 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7344 c[3] *= rsurface.texture->currentalpha;
7354 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7356 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7357 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7358 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7361 // brighten it up (as texture value 127 means "unlit")
7362 c[0] *= 2 * r_refdef.view.colorscale;
7363 c[1] *= 2 * r_refdef.view.colorscale;
7364 c[2] *= 2 * r_refdef.view.colorscale;
7366 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7367 c[3] *= r_wateralpha.value;
7369 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7371 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7372 GL_DepthMask(false);
7374 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7376 GL_BlendFunc(GL_ONE, GL_ONE);
7377 GL_DepthMask(false);
7379 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7381 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7382 GL_DepthMask(false);
7384 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7386 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7387 GL_DepthMask(false);
7391 GL_BlendFunc(GL_ONE, GL_ZERO);
7392 GL_DepthMask(writedepth);
7395 rsurface.lightmapcolor4f = NULL;
7397 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7399 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7401 rsurface.lightmapcolor4f = NULL;
7402 rsurface.lightmapcolor4f_bufferobject = 0;
7403 rsurface.lightmapcolor4f_bufferoffset = 0;
7405 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7407 qboolean applycolor = true;
7410 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7412 r_refdef.lightmapintensity = 1;
7413 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7414 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7418 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7420 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7421 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7422 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7425 if(!rsurface.lightmapcolor4f)
7426 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7428 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7429 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7430 if(r_refdef.fogenabled)
7431 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7433 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7434 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7437 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7440 RSurf_SetupDepthAndCulling();
7441 if (r_showsurfaces.integer == 3)
7442 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7443 else if (r_glsl.integer && gl_support_fragment_shader)
7444 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7445 else if (gl_combine.integer && r_textureunits.integer >= 2)
7446 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7448 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7452 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7455 RSurf_SetupDepthAndCulling();
7456 if (r_showsurfaces.integer == 3)
7457 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7458 else if (r_glsl.integer && gl_support_fragment_shader)
7459 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7460 else if (gl_combine.integer && r_textureunits.integer >= 2)
7461 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7463 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7467 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7470 int texturenumsurfaces, endsurface;
7472 msurface_t *surface;
7473 msurface_t *texturesurfacelist[1024];
7475 // if the model is static it doesn't matter what value we give for
7476 // wantnormals and wanttangents, so this logic uses only rules applicable
7477 // to a model, knowing that they are meaningless otherwise
7478 if (ent == r_refdef.scene.worldentity)
7479 RSurf_ActiveWorldEntity();
7480 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7481 RSurf_ActiveModelEntity(ent, false, false);
7483 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7485 for (i = 0;i < numsurfaces;i = j)
7488 surface = rsurface.modelsurfaces + surfacelist[i];
7489 texture = surface->texture;
7490 rsurface.texture = R_GetCurrentTexture(texture);
7491 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7492 // scan ahead until we find a different texture
7493 endsurface = min(i + 1024, numsurfaces);
7494 texturenumsurfaces = 0;
7495 texturesurfacelist[texturenumsurfaces++] = surface;
7496 for (;j < endsurface;j++)
7498 surface = rsurface.modelsurfaces + surfacelist[j];
7499 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7501 texturesurfacelist[texturenumsurfaces++] = surface;
7503 // render the range of surfaces
7504 if (ent == r_refdef.scene.worldentity)
7505 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7507 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7509 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7510 GL_AlphaTest(false);
7513 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7515 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7519 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7521 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7523 RSurf_SetupDepthAndCulling();
7524 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7525 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7527 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7529 RSurf_SetupDepthAndCulling();
7530 GL_AlphaTest(false);
7531 R_Mesh_ColorPointer(NULL, 0, 0);
7532 R_Mesh_ResetTextureState();
7533 R_SetupGenericShader(false);
7534 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7536 GL_BlendFunc(GL_ONE, GL_ZERO);
7537 GL_Color(0, 0, 0, 1);
7538 GL_DepthTest(writedepth);
7539 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7541 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7543 RSurf_SetupDepthAndCulling();
7544 GL_AlphaTest(false);
7545 R_Mesh_ColorPointer(NULL, 0, 0);
7546 R_Mesh_ResetTextureState();
7547 R_SetupGenericShader(false);
7548 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7550 GL_BlendFunc(GL_ONE, GL_ZERO);
7552 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7554 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7555 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7556 else if (!rsurface.texture->currentnumlayers)
7558 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7560 // transparent surfaces get pushed off into the transparent queue
7561 int surfacelistindex;
7562 const msurface_t *surface;
7563 vec3_t tempcenter, center;
7564 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7566 surface = texturesurfacelist[surfacelistindex];
7567 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7568 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7569 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7570 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7571 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7576 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7577 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7582 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7586 // break the surface list down into batches by texture and use of lightmapping
7587 for (i = 0;i < numsurfaces;i = j)
7590 // texture is the base texture pointer, rsurface.texture is the
7591 // current frame/skin the texture is directing us to use (for example
7592 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7593 // use skin 1 instead)
7594 texture = surfacelist[i]->texture;
7595 rsurface.texture = R_GetCurrentTexture(texture);
7596 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7597 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7599 // if this texture is not the kind we want, skip ahead to the next one
7600 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7604 // simply scan ahead until we find a different texture or lightmap state
7605 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7607 // render the range of surfaces
7608 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7612 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7617 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7619 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7621 RSurf_SetupDepthAndCulling();
7622 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7623 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7625 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7627 RSurf_SetupDepthAndCulling();
7628 GL_AlphaTest(false);
7629 R_Mesh_ColorPointer(NULL, 0, 0);
7630 R_Mesh_ResetTextureState();
7631 R_SetupGenericShader(false);
7632 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7634 GL_BlendFunc(GL_ONE, GL_ZERO);
7635 GL_Color(0, 0, 0, 1);
7636 GL_DepthTest(writedepth);
7637 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7639 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7641 RSurf_SetupDepthAndCulling();
7642 GL_AlphaTest(false);
7643 R_Mesh_ColorPointer(NULL, 0, 0);
7644 R_Mesh_ResetTextureState();
7645 R_SetupGenericShader(false);
7646 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7648 GL_BlendFunc(GL_ONE, GL_ZERO);
7650 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7652 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7653 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7654 else if (!rsurface.texture->currentnumlayers)
7656 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7658 // transparent surfaces get pushed off into the transparent queue
7659 int surfacelistindex;
7660 const msurface_t *surface;
7661 vec3_t tempcenter, center;
7662 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7664 surface = texturesurfacelist[surfacelistindex];
7665 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7666 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7667 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7668 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7669 if (queueentity->transparent_offset) // transparent offset
7671 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
7672 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
7673 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
7675 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7680 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7681 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7686 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7690 // break the surface list down into batches by texture and use of lightmapping
7691 for (i = 0;i < numsurfaces;i = j)
7694 // texture is the base texture pointer, rsurface.texture is the
7695 // current frame/skin the texture is directing us to use (for example
7696 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7697 // use skin 1 instead)
7698 texture = surfacelist[i]->texture;
7699 rsurface.texture = R_GetCurrentTexture(texture);
7700 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7701 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7703 // if this texture is not the kind we want, skip ahead to the next one
7704 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7708 // simply scan ahead until we find a different texture or lightmap state
7709 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7711 // render the range of surfaces
7712 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7716 float locboxvertex3f[6*4*3] =
7718 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7719 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7720 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7721 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7722 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7723 1,0,0, 0,0,0, 0,1,0, 1,1,0
7726 unsigned short locboxelements[6*2*3] =
7736 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7739 cl_locnode_t *loc = (cl_locnode_t *)ent;
7741 float vertex3f[6*4*3];
7743 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7744 GL_DepthMask(false);
7745 GL_DepthRange(0, 1);
7746 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7748 GL_CullFace(GL_NONE);
7749 R_Mesh_Matrix(&identitymatrix);
7751 R_Mesh_VertexPointer(vertex3f, 0, 0);
7752 R_Mesh_ColorPointer(NULL, 0, 0);
7753 R_Mesh_ResetTextureState();
7754 R_SetupGenericShader(false);
7757 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7758 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7759 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7760 surfacelist[0] < 0 ? 0.5f : 0.125f);
7762 if (VectorCompare(loc->mins, loc->maxs))
7764 VectorSet(size, 2, 2, 2);
7765 VectorMA(loc->mins, -0.5f, size, mins);
7769 VectorCopy(loc->mins, mins);
7770 VectorSubtract(loc->maxs, loc->mins, size);
7773 for (i = 0;i < 6*4*3;)
7774 for (j = 0;j < 3;j++, i++)
7775 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7777 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7780 void R_DrawLocs(void)
7783 cl_locnode_t *loc, *nearestloc;
7785 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7786 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7788 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7789 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7793 void R_DrawDebugModel(entity_render_t *ent)
7795 int i, j, k, l, flagsmask;
7796 const int *elements;
7798 msurface_t *surface;
7799 dp_model_t *model = ent->model;
7802 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7804 R_Mesh_ColorPointer(NULL, 0, 0);
7805 R_Mesh_ResetTextureState();
7806 R_SetupGenericShader(false);
7807 GL_DepthRange(0, 1);
7808 GL_DepthTest(!r_showdisabledepthtest.integer);
7809 GL_DepthMask(false);
7810 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7812 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7814 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7815 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7817 if (brush->colbrushf && brush->colbrushf->numtriangles)
7819 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7820 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);
7821 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7824 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7826 if (surface->num_collisiontriangles)
7828 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7829 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);
7830 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7835 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7837 if (r_showtris.integer || r_shownormals.integer)
7839 if (r_showdisabledepthtest.integer)
7841 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7842 GL_DepthMask(false);
7846 GL_BlendFunc(GL_ONE, GL_ZERO);
7849 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7851 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7853 rsurface.texture = R_GetCurrentTexture(surface->texture);
7854 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7856 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7857 if (r_showtris.value > 0)
7859 if (!rsurface.texture->currentlayers->depthmask)
7860 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7861 else if (ent == r_refdef.scene.worldentity)
7862 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7864 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7865 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7866 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7867 R_Mesh_ColorPointer(NULL, 0, 0);
7868 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7869 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7870 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7871 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);
7872 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7875 if (r_shownormals.value < 0)
7878 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7880 VectorCopy(rsurface.vertex3f + l * 3, v);
7881 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7882 qglVertex3f(v[0], v[1], v[2]);
7883 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7884 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7885 qglVertex3f(v[0], v[1], v[2]);
7890 if (r_shownormals.value > 0)
7893 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7895 VectorCopy(rsurface.vertex3f + l * 3, v);
7896 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7897 qglVertex3f(v[0], v[1], v[2]);
7898 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7899 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7900 qglVertex3f(v[0], v[1], v[2]);
7905 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7907 VectorCopy(rsurface.vertex3f + l * 3, v);
7908 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7909 qglVertex3f(v[0], v[1], v[2]);
7910 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7911 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7912 qglVertex3f(v[0], v[1], v[2]);
7917 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7919 VectorCopy(rsurface.vertex3f + l * 3, v);
7920 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7921 qglVertex3f(v[0], v[1], v[2]);
7922 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7923 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7924 qglVertex3f(v[0], v[1], v[2]);
7931 rsurface.texture = NULL;
7935 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7936 int r_maxsurfacelist = 0;
7937 msurface_t **r_surfacelist = NULL;
7938 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7940 int i, j, endj, f, flagsmask;
7942 dp_model_t *model = r_refdef.scene.worldmodel;
7943 msurface_t *surfaces;
7944 unsigned char *update;
7945 int numsurfacelist = 0;
7949 if (r_maxsurfacelist < model->num_surfaces)
7951 r_maxsurfacelist = model->num_surfaces;
7953 Mem_Free(r_surfacelist);
7954 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7957 RSurf_ActiveWorldEntity();
7959 surfaces = model->data_surfaces;
7960 update = model->brushq1.lightmapupdateflags;
7962 // update light styles on this submodel
7963 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7965 model_brush_lightstyleinfo_t *style;
7966 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7968 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7970 int *list = style->surfacelist;
7971 style->value = r_refdef.scene.lightstylevalue[style->style];
7972 for (j = 0;j < style->numsurfaces;j++)
7973 update[list[j]] = true;
7978 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7982 R_DrawDebugModel(r_refdef.scene.worldentity);
7983 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7989 rsurface.uselightmaptexture = false;
7990 rsurface.texture = NULL;
7991 rsurface.rtlight = NULL;
7993 // add visible surfaces to draw list
7994 for (i = 0;i < model->nummodelsurfaces;i++)
7996 j = model->sortedmodelsurfaces[i];
7997 if (r_refdef.viewcache.world_surfacevisible[j])
7998 r_surfacelist[numsurfacelist++] = surfaces + j;
8000 // update lightmaps if needed
8002 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8003 if (r_refdef.viewcache.world_surfacevisible[j])
8005 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8006 // don't do anything if there were no surfaces
8007 if (!numsurfacelist)
8009 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8012 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8013 GL_AlphaTest(false);
8015 // add to stats if desired
8016 if (r_speeds.integer && !skysurfaces && !depthonly)
8018 r_refdef.stats.world_surfaces += numsurfacelist;
8019 for (j = 0;j < numsurfacelist;j++)
8020 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8022 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8025 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8027 int i, j, endj, f, flagsmask;
8029 dp_model_t *model = ent->model;
8030 msurface_t *surfaces;
8031 unsigned char *update;
8032 int numsurfacelist = 0;
8036 if (r_maxsurfacelist < model->num_surfaces)
8038 r_maxsurfacelist = model->num_surfaces;
8040 Mem_Free(r_surfacelist);
8041 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8044 // if the model is static it doesn't matter what value we give for
8045 // wantnormals and wanttangents, so this logic uses only rules applicable
8046 // to a model, knowing that they are meaningless otherwise
8047 if (ent == r_refdef.scene.worldentity)
8048 RSurf_ActiveWorldEntity();
8049 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8050 RSurf_ActiveModelEntity(ent, false, false);
8052 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8054 surfaces = model->data_surfaces;
8055 update = model->brushq1.lightmapupdateflags;
8057 // update light styles
8058 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8060 model_brush_lightstyleinfo_t *style;
8061 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8063 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8065 int *list = style->surfacelist;
8066 style->value = r_refdef.scene.lightstylevalue[style->style];
8067 for (j = 0;j < style->numsurfaces;j++)
8068 update[list[j]] = true;
8073 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8077 R_DrawDebugModel(ent);
8078 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8084 rsurface.uselightmaptexture = false;
8085 rsurface.texture = NULL;
8086 rsurface.rtlight = NULL;
8088 // add visible surfaces to draw list
8089 for (i = 0;i < model->nummodelsurfaces;i++)
8090 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8091 // don't do anything if there were no surfaces
8092 if (!numsurfacelist)
8094 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8097 // update lightmaps if needed
8099 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8101 R_BuildLightMap(ent, surfaces + j);
8102 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8103 GL_AlphaTest(false);
8105 // add to stats if desired
8106 if (r_speeds.integer && !skysurfaces && !depthonly)
8108 r_refdef.stats.entities_surfaces += numsurfacelist;
8109 for (j = 0;j < numsurfacelist;j++)
8110 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8112 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity