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
33 qboolean r_loadnormalmap;
42 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
43 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
44 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
45 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
46 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)"};
47 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
48 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
49 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
51 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
52 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
53 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
54 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
55 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
57 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"};
58 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
59 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
60 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
61 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
62 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
63 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)"};
64 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
65 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
66 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"};
67 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"};
68 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
69 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"};
70 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"};
71 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"};
72 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
73 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
74 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
75 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
76 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
77 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
78 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
79 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
80 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
81 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
82 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
83 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
84 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
85 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."};
86 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
87 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
88 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
89 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."};
90 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
91 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
92 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"};
93 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
94 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
95 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
96 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
97 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
98 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "1", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
100 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
101 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
102 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
103 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
104 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
105 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
106 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
107 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
109 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
110 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
111 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
113 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)"};
114 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
115 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
116 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
117 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
118 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)"};
119 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)"};
120 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)"};
121 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)"};
123 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)"};
124 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
125 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"};
126 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
127 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
129 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
130 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
131 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
132 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
134 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
135 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
136 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
137 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
138 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
139 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
140 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
142 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
143 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
144 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
145 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)"};
147 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"};
149 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"};
151 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
153 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
154 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
155 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"};
156 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
157 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
158 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
159 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
161 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
163 extern cvar_t v_glslgamma;
165 extern qboolean v_flipped_state;
167 static struct r_bloomstate_s
172 int bloomwidth, bloomheight;
174 int screentexturewidth, screentextureheight;
175 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
177 int bloomtexturewidth, bloomtextureheight;
178 rtexture_t *texture_bloom;
180 // arrays for rendering the screen passes
181 float screentexcoord2f[8];
182 float bloomtexcoord2f[8];
183 float offsettexcoord2f[8];
185 r_viewport_t viewport;
189 r_waterstate_t r_waterstate;
191 /// shadow volume bsp struct with automatically growing nodes buffer
194 rtexture_t *r_texture_blanknormalmap;
195 rtexture_t *r_texture_white;
196 rtexture_t *r_texture_grey128;
197 rtexture_t *r_texture_black;
198 rtexture_t *r_texture_notexture;
199 rtexture_t *r_texture_whitecube;
200 rtexture_t *r_texture_normalizationcube;
201 rtexture_t *r_texture_fogattenuation;
202 rtexture_t *r_texture_gammaramps;
203 unsigned int r_texture_gammaramps_serial;
204 //rtexture_t *r_texture_fogintensity;
206 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
207 unsigned int r_numqueries;
208 unsigned int r_maxqueries;
210 typedef struct r_qwskincache_s
212 char name[MAX_QPATH];
213 skinframe_t *skinframe;
217 static r_qwskincache_t *r_qwskincache;
218 static int r_qwskincache_size;
220 /// vertex coordinates for a quad that covers the screen exactly
221 const float r_screenvertex3f[12] =
229 extern void R_DrawModelShadows(void);
231 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
234 for (i = 0;i < verts;i++)
245 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
248 for (i = 0;i < verts;i++)
258 // FIXME: move this to client?
261 if (gamemode == GAME_NEHAHRA)
263 Cvar_Set("gl_fogenable", "0");
264 Cvar_Set("gl_fogdensity", "0.2");
265 Cvar_Set("gl_fogred", "0.3");
266 Cvar_Set("gl_foggreen", "0.3");
267 Cvar_Set("gl_fogblue", "0.3");
269 r_refdef.fog_density = 0;
270 r_refdef.fog_red = 0;
271 r_refdef.fog_green = 0;
272 r_refdef.fog_blue = 0;
273 r_refdef.fog_alpha = 1;
274 r_refdef.fog_start = 0;
275 r_refdef.fog_end = 16384;
276 r_refdef.fog_height = 1<<30;
277 r_refdef.fog_fadedepth = 128;
280 static void R_BuildBlankTextures(void)
282 unsigned char data[4];
283 data[2] = 128; // normal X
284 data[1] = 128; // normal Y
285 data[0] = 255; // normal Z
286 data[3] = 128; // height
287 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
297 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
302 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
305 static void R_BuildNoTexture(void)
308 unsigned char pix[16][16][4];
309 // this makes a light grey/dark grey checkerboard texture
310 for (y = 0;y < 16;y++)
312 for (x = 0;x < 16;x++)
314 if ((y < 8) ^ (x < 8))
330 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
333 static void R_BuildWhiteCube(void)
335 unsigned char data[6*1*1*4];
336 memset(data, 255, sizeof(data));
337 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
340 static void R_BuildNormalizationCube(void)
344 vec_t s, t, intensity;
346 unsigned char data[6][NORMSIZE][NORMSIZE][4];
347 for (side = 0;side < 6;side++)
349 for (y = 0;y < NORMSIZE;y++)
351 for (x = 0;x < NORMSIZE;x++)
353 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
354 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
389 intensity = 127.0f / sqrt(DotProduct(v, v));
390 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
391 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
392 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
393 data[side][y][x][3] = 255;
397 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
400 static void R_BuildFogTexture(void)
404 unsigned char data1[FOGWIDTH][4];
405 //unsigned char data2[FOGWIDTH][4];
408 r_refdef.fogmasktable_start = r_refdef.fog_start;
409 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
410 r_refdef.fogmasktable_range = r_refdef.fogrange;
411 r_refdef.fogmasktable_density = r_refdef.fog_density;
413 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
414 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
416 d = (x * r - r_refdef.fogmasktable_start);
417 if(developer.integer >= 100)
418 Con_Printf("%f ", d);
420 if (r_fog_exp2.integer)
421 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
423 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
424 if(developer.integer >= 100)
425 Con_Printf(" : %f ", alpha);
426 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
427 if(developer.integer >= 100)
428 Con_Printf(" = %f\n", alpha);
429 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
432 for (x = 0;x < FOGWIDTH;x++)
434 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
439 //data2[x][0] = 255 - b;
440 //data2[x][1] = 255 - b;
441 //data2[x][2] = 255 - b;
444 if (r_texture_fogattenuation)
446 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
447 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
451 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);
452 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
456 static const char *builtinshaderstring =
457 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
458 "// written by Forest 'LordHavoc' Hale\n"
460 "// enable various extensions depending on permutation:\n"
462 "#ifdef MODE_DEPTH_OR_SHADOW\n"
463 "#ifdef VERTEX_SHADER\n"
466 " gl_Position = ftransform();\n"
469 "#else // !MODE_DEPTH_ORSHADOW\n"
470 "#ifdef MODE_SHOWDEPTH\n"
471 "#ifdef VERTEX_SHADER\n"
474 " gl_Position = ftransform();\n"
475 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
479 "#ifdef FRAGMENT_SHADER\n"
482 " gl_FragColor = gl_Color;\n"
485 "#else // !MODE_SHOWDEPTH\n"
486 "#ifdef MODE_POSTPROCESS\n"
487 "#ifdef VERTEX_SHADER\n"
490 " gl_Position = ftransform();\n"
491 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
493 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
498 "#ifdef FRAGMENT_SHADER\n"
499 "uniform sampler2D Texture_First;\n"
501 "uniform sampler2D Texture_Second;\n"
503 "#ifdef USEGAMMARAMPS\n"
504 "uniform sampler2D Texture_GammaRamps;\n"
506 "#ifdef USESATURATION\n"
507 "uniform float Saturation;\n"
509 "#ifdef USEVIEWTINT\n"
510 "uniform vec4 ViewTintColor;\n"
512 "//uncomment these if you want to use them:\n"
513 "uniform vec4 UserVec1;\n"
514 "// uniform vec4 UserVec2;\n"
515 "// uniform vec4 UserVec3;\n"
516 "// uniform vec4 UserVec4;\n"
517 "// uniform float ClientTime;\n"
518 "uniform vec2 PixelSize;\n"
521 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
523 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
525 "#ifdef USEVIEWTINT\n"
526 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
529 "#ifdef USEPOSTPROCESSING\n"
530 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
531 "// 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"
532 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
533 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
534 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
535 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
536 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
537 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
540 "#ifdef USESATURATION\n"
541 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
542 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
543 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
544 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
547 "#ifdef USEGAMMARAMPS\n"
548 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
549 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
550 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
554 "#else // !MODE_POSTPROCESS\n"
555 "#ifdef MODE_GENERIC\n"
556 "#ifdef VERTEX_SHADER\n"
559 " gl_FrontColor = gl_Color;\n"
560 "#ifdef USEDIFFUSE\n"
561 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
563 "#ifdef USESPECULAR\n"
564 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
566 " gl_Position = ftransform();\n"
570 "#ifdef FRAGMENT_SHADER\n"
571 "#ifdef USEDIFFUSE\n"
572 "uniform sampler2D Texture_First;\n"
574 "#ifdef USESPECULAR\n"
575 "uniform sampler2D Texture_Second;\n"
580 " gl_FragColor = gl_Color;\n"
581 "#ifdef USEDIFFUSE\n"
582 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
585 "#ifdef USESPECULAR\n"
586 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
588 "#ifdef USECOLORMAPPING\n"
589 " gl_FragColor *= tex2;\n"
592 " gl_FragColor += tex2;\n"
594 "#ifdef USEVERTEXTEXTUREBLEND\n"
595 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
599 "#else // !MODE_GENERIC\n"
600 "#ifdef MODE_BLOOMBLUR\n"
601 "#ifdef VERTEX_SHADER\n"
604 " gl_FrontColor = gl_Color;\n"
605 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
606 " gl_Position = ftransform();\n"
610 "#ifdef FRAGMENT_SHADER\n"
611 "uniform sampler2D Texture_First;\n"
612 "uniform vec4 BloomBlur_Parameters;\n"
617 " vec2 tc = gl_TexCoord[0].xy;\n"
618 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
619 " tc += BloomBlur_Parameters.xy;\n"
620 " for (i = 1;i < SAMPLES;i++)\n"
622 " color += texture2D(Texture_First, tc).rgb;\n"
623 " tc += BloomBlur_Parameters.xy;\n"
625 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
628 "#else // !MODE_BLOOMBLUR\n"
629 "#ifdef MODE_REFRACTION\n"
630 "varying vec2 TexCoord;\n"
631 "varying vec4 ModelViewProjectionPosition;\n"
632 "#ifdef VERTEX_SHADER\n"
636 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
637 " gl_Position = ftransform();\n"
638 " ModelViewProjectionPosition = gl_Position;\n"
642 "#ifdef FRAGMENT_SHADER\n"
643 "uniform sampler2D Texture_Normal;\n"
644 "uniform sampler2D Texture_Refraction;\n"
645 "uniform sampler2D Texture_Reflection;\n"
647 "uniform vec4 DistortScaleRefractReflect;\n"
648 "uniform vec4 ScreenScaleRefractReflect;\n"
649 "uniform vec4 ScreenCenterRefractReflect;\n"
650 "uniform vec4 RefractColor;\n"
651 "uniform vec4 ReflectColor;\n"
652 "uniform float ReflectFactor;\n"
653 "uniform float ReflectOffset;\n"
657 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
658 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
659 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
660 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
661 " // FIXME temporary hack to detect the case that the reflection\n"
662 " // gets blackened at edges due to leaving the area that contains actual\n"
664 " // Remove this 'ack once we have a better way to stop this thing from\n"
666 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
667 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
668 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
669 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
670 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
671 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
674 "#else // !MODE_REFRACTION\n"
675 "#ifdef MODE_WATER\n"
676 "varying vec2 TexCoord;\n"
677 "varying vec3 EyeVector;\n"
678 "varying vec4 ModelViewProjectionPosition;\n"
679 "#ifdef VERTEX_SHADER\n"
680 "uniform vec3 EyePosition;\n"
684 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
685 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
686 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
687 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
688 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
689 " gl_Position = ftransform();\n"
690 " ModelViewProjectionPosition = gl_Position;\n"
694 "#ifdef FRAGMENT_SHADER\n"
695 "uniform sampler2D Texture_Normal;\n"
696 "uniform sampler2D Texture_Refraction;\n"
697 "uniform sampler2D Texture_Reflection;\n"
699 "uniform vec4 DistortScaleRefractReflect;\n"
700 "uniform vec4 ScreenScaleRefractReflect;\n"
701 "uniform vec4 ScreenCenterRefractReflect;\n"
702 "uniform vec4 RefractColor;\n"
703 "uniform vec4 ReflectColor;\n"
704 "uniform float ReflectFactor;\n"
705 "uniform float ReflectOffset;\n"
709 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
710 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
711 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
712 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
713 " // FIXME temporary hack to detect the case that the reflection\n"
714 " // gets blackened at edges due to leaving the area that contains actual\n"
716 " // Remove this 'ack once we have a better way to stop this thing from\n"
718 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
719 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
720 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
721 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
722 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
723 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
724 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
725 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
726 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
727 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
728 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
729 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
732 "#else // !MODE_WATER\n"
734 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
735 "# extension GL_ARB_texture_rectangle : enable\n"
738 "#ifdef USESHADOWMAP2D\n"
739 "# ifdef GL_EXT_gpu_shader4\n"
740 "# extension GL_EXT_gpu_shader4 : enable\n"
742 "# ifdef GL_ARB_texture_gather\n"
743 "# extension GL_ARB_texture_gather : enable\n"
745 "# ifdef GL_AMD_texture_texture4\n"
746 "# extension GL_AMD_texture_texture4 : enable\n"
751 "#ifdef USESHADOWMAPCUBE\n"
752 "# extension GL_EXT_gpu_shader4 : enable\n"
755 "#ifdef USESHADOWSAMPLER\n"
756 "# extension GL_ARB_shadow : enable\n"
759 "// common definitions between vertex shader and fragment shader:\n"
761 "//#ifdef __GLSL_CG_DATA_TYPES\n"
762 "//# define myhalf half\n"
763 "//# define myhalf2 half2\n"
764 "//# define myhalf3half3\n"
765 "//# define myhalf4 half4\n"
767 "# define myhalf float\n"
768 "# define myhalf2 vec2\n"
769 "# define myhalf3 vec3\n"
770 "# define myhalf4 vec4\n"
773 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
777 "varying vec2 TexCoord;\n"
778 "#ifdef USEVERTEXTEXTUREBLEND\n"
779 "varying vec2 TexCoord2;\n"
781 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
782 "#define USELIGHTMAP\n"
783 "varying vec2 TexCoordLightmap;\n"
786 "#ifdef MODE_LIGHTSOURCE\n"
787 "varying vec3 CubeVector;\n"
790 "#ifdef MODE_LIGHTSOURCE\n"
791 "varying vec3 LightVector;\n"
793 "#if defined(MODE_LIGHTDIRECTION)\n"
794 "varying vec3 LightVector;\n"
797 "#if defined(USEOFFSETMAPPING) || defined(USESPECULAR)\n"
798 "//#if defined(USEOFFSETMAPPING) || defined(USESPECULAR) || defined(MODE_LIGHTDIRECTION) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
799 "#define USEEYEVECTOR\n"
800 "varying vec3 EyeVector;\n"
803 "varying vec3 EyeVectorModelSpace;\n"
804 "varying float FogPlaneVertexDist;\n"
807 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
808 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
809 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
810 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
813 "#ifdef USEREFLECTION\n"
814 "varying vec4 ModelViewProjectionPosition;\n"
816 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
817 "uniform vec3 LightPosition;\n"
818 "varying vec4 ModelViewPosition;\n"
821 "#ifdef MODE_LIGHTSOURCE\n"
822 "uniform vec3 LightPosition;\n"
824 "uniform vec3 EyePosition;\n"
825 "#ifdef MODE_LIGHTDIRECTION\n"
826 "uniform vec3 LightDir;\n"
828 "uniform vec4 FogPlane;\n"
834 "// vertex shader specific:\n"
835 "#ifdef VERTEX_SHADER\n"
837 "// 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"
839 "#ifdef MODE_DEFERREDGEOMETRY\n"
842 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
843 "#ifdef USEVERTEXTEXTUREBLEND\n"
844 " gl_FrontColor = gl_Color;\n"
845 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
848 " // transform unnormalized eye direction into tangent space\n"
849 "#ifdef USEOFFSETMAPPING\n"
850 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
851 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
852 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
853 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
856 " VectorS = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz).xyz;\n"
857 " VectorT = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz).xyz;\n"
858 " VectorR = normalize(gl_NormalMatrix * gl_MultiTexCoord3.xyz).xyz;\n"
859 " gl_Position = ftransform();\n"
861 "#else // !MODE_DEFERREDGEOMETRY\n"
862 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
865 " ModelViewPosition = gl_ModelViewMatrix * gl_Vertex;\n"
866 " gl_Position = ftransform();\n"
868 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
871 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
872 " gl_FrontColor = gl_Color;\n"
874 " // copy the surface texcoord\n"
875 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
876 "#ifdef USEVERTEXTEXTUREBLEND\n"
877 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
879 "#ifdef USELIGHTMAP\n"
880 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
883 "#ifdef MODE_LIGHTSOURCE\n"
884 " // transform vertex position into light attenuation/cubemap space\n"
885 " // (-1 to +1 across the light box)\n"
886 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
888 "# ifdef USEDIFFUSE\n"
889 " // transform unnormalized light direction into tangent space\n"
890 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
891 " // normalize it per pixel)\n"
892 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
893 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
894 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
895 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
899 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
900 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
901 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
902 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
905 " // transform unnormalized eye direction into tangent space\n"
906 "#ifdef USEEYEVECTOR\n"
908 " vec3 EyeVectorModelSpace;\n"
910 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
911 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
912 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
913 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
917 "#ifndef USEEYEVECTOR\n"
918 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
920 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
923 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
924 " VectorS = gl_MultiTexCoord1.xyz;\n"
925 " VectorT = gl_MultiTexCoord2.xyz;\n"
926 " VectorR = gl_MultiTexCoord3.xyz;\n"
929 "//#if defined(USEREFLECTION)\n"
930 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
931 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
932 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
935 "// transform vertex to camera space, using ftransform to match non-VS\n"
937 " gl_Position = ftransform();\n"
939 "#ifdef USEREFLECTION\n"
940 " ModelViewProjectionPosition = gl_Position;\n"
943 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
944 "#endif // !MODE_DEFERREDGEOMETRY\n"
946 "#endif // VERTEX_SHADER\n"
951 "// fragment shader specific:\n"
952 "#ifdef FRAGMENT_SHADER\n"
954 "uniform sampler2D Texture_Normal;\n"
955 "uniform sampler2D Texture_Color;\n"
956 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
957 "uniform sampler2D Texture_Gloss;\n"
960 "uniform sampler2D Texture_Glow;\n"
962 "#ifdef USEVERTEXTEXTUREBLEND\n"
963 "uniform sampler2D Texture_SecondaryNormal;\n"
964 "uniform sampler2D Texture_SecondaryColor;\n"
965 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
966 "uniform sampler2D Texture_SecondaryGloss;\n"
969 "uniform sampler2D Texture_SecondaryGlow;\n"
972 "#ifdef USECOLORMAPPING\n"
973 "uniform sampler2D Texture_Pants;\n"
974 "uniform sampler2D Texture_Shirt;\n"
977 "uniform sampler2D Texture_FogMask;\n"
979 "#ifdef USELIGHTMAP\n"
980 "uniform sampler2D Texture_Lightmap;\n"
982 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
983 "uniform sampler2D Texture_Deluxemap;\n"
985 "#ifdef USEREFLECTION\n"
986 "uniform sampler2D Texture_Reflection;\n"
989 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
990 "uniform sampler2DRect Texture_ScreenDepth;\n"
991 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
993 "#ifdef USEDEFERREDLIGHTMAP\n"
994 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
995 "uniform sampler2DRect Texture_ScreenSpecular;\n"
998 "uniform myhalf3 Color_Pants;\n"
999 "uniform myhalf3 Color_Shirt;\n"
1000 "uniform myhalf3 FogColor;\n"
1003 "uniform float FogRangeRecip;\n"
1004 "uniform float FogPlaneViewDist;\n"
1005 "uniform float FogHeightFade;\n"
1006 "myhalf FogVertex(void)\n"
1009 "#ifdef USEFOGOUTSIDE\n"
1010 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1012 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1014 " return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1018 "#ifdef USEOFFSETMAPPING\n"
1019 "uniform float OffsetMapping_Scale;\n"
1020 "vec2 OffsetMapping(vec2 TexCoord)\n"
1022 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1023 " // 14 sample relief mapping: linear search and then binary search\n"
1024 " // this basically steps forward a small amount repeatedly until it finds\n"
1025 " // itself inside solid, then jitters forward and back using decreasing\n"
1026 " // amounts to find the impact\n"
1027 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1028 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1029 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1030 " vec3 RT = vec3(TexCoord, 1);\n"
1031 " OffsetVector *= 0.1;\n"
1032 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1033 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1034 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1035 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1036 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1037 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1038 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1039 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1040 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1041 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1042 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1043 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1044 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1045 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1048 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1049 " // this basically moves forward the full distance, and then backs up based\n"
1050 " // on height of samples\n"
1051 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1052 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1053 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1054 " TexCoord += OffsetVector;\n"
1055 " OffsetVector *= 0.333;\n"
1056 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1057 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1058 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1059 " return TexCoord;\n"
1062 "#endif // USEOFFSETMAPPING\n"
1064 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1065 "uniform sampler2D Texture_Attenuation;\n"
1066 "uniform samplerCube Texture_Cube;\n"
1068 "#ifdef USESHADOWMAPRECT\n"
1069 "# ifdef USESHADOWSAMPLER\n"
1070 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1072 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1076 "#ifdef USESHADOWMAP2D\n"
1077 "# ifdef USESHADOWSAMPLER\n"
1078 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1080 "uniform sampler2D Texture_ShadowMap2D;\n"
1084 "#ifdef USESHADOWMAPVSDCT\n"
1085 "uniform samplerCube Texture_CubeProjection;\n"
1088 "#ifdef USESHADOWMAPCUBE\n"
1089 "# ifdef USESHADOWSAMPLER\n"
1090 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1092 "uniform samplerCube Texture_ShadowMapCube;\n"
1096 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1097 "uniform vec2 ShadowMap_TextureScale;\n"
1098 "uniform vec4 ShadowMap_Parameters;\n"
1101 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1102 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1104 " vec3 adir = abs(dir);\n"
1105 "# ifndef USESHADOWMAPVSDCT\n"
1109 " if (adir.x > adir.y)\n"
1111 " if (adir.x > adir.z) // X\n"
1115 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1121 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1126 " if (adir.y > adir.z) // Y\n"
1130 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1136 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1140 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1141 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1142 " stc.z += ShadowMap_Parameters.z;\n"
1145 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1146 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1147 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1148 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1149 " stc.z += ShadowMap_Parameters.z;\n"
1153 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1155 "#ifdef USESHADOWMAPCUBE\n"
1156 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1158 " vec3 adir = abs(dir);\n"
1159 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1163 "# ifdef USESHADOWMAPRECT\n"
1164 "float ShadowMapCompare(vec3 dir)\n"
1166 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1168 "# ifdef USESHADOWSAMPLER\n"
1170 "# ifdef USESHADOWMAPPCF\n"
1171 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1172 " 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"
1174 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1179 "# ifdef USESHADOWMAPPCF\n"
1180 "# if USESHADOWMAPPCF > 1\n"
1181 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1182 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1183 " 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"
1184 " 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"
1185 " 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"
1186 " 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"
1187 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1188 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1190 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1191 " vec2 offset = fract(shadowmaptc.xy);\n"
1192 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1193 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1194 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1195 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1196 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1199 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1207 "# ifdef USESHADOWMAP2D\n"
1208 "float ShadowMapCompare(vec3 dir)\n"
1210 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1213 "# ifdef USESHADOWSAMPLER\n"
1214 "# ifdef USESHADOWMAPPCF\n"
1215 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1216 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1217 " 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"
1219 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1222 "# ifdef USESHADOWMAPPCF\n"
1223 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1224 "# ifdef GL_ARB_texture_gather\n"
1225 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1227 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1229 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1230 " center *= ShadowMap_TextureScale;\n"
1231 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1232 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1233 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1234 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1235 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1236 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1237 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1239 "# ifdef GL_EXT_gpu_shader4\n"
1240 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1242 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1244 "# if USESHADOWMAPPCF > 1\n"
1245 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1246 " center *= ShadowMap_TextureScale;\n"
1247 " 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"
1248 " 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"
1249 " 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"
1250 " 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"
1251 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1252 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1254 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1255 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1256 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1257 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1258 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1259 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1263 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1270 "# ifdef USESHADOWMAPCUBE\n"
1271 "float ShadowMapCompare(vec3 dir)\n"
1273 " // apply depth texture cubemap as light filter\n"
1274 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1276 "# ifdef USESHADOWSAMPLER\n"
1277 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1279 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1284 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1286 "#ifdef MODE_DEFERREDGEOMETRY\n"
1289 "#ifdef USEOFFSETMAPPING\n"
1290 " // apply offsetmapping\n"
1291 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1292 "#define TexCoord TexCoordOffset\n"
1295 "#ifdef USEALPHAKILL\n"
1296 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1300 "#ifdef USEVERTEXTEXTUREBLEND\n"
1301 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1302 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1303 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1304 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1307 "#ifdef USEVERTEXTEXTUREBLEND\n"
1308 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1310 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1313 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1315 "#else // !MODE_DEFERREDGEOMETRY\n"
1316 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1317 "uniform mat4 ViewToLight;\n"
1318 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1319 "uniform vec2 ScreenToDepth;\n"
1320 "uniform myhalf3 DeferredColor_Ambient;\n"
1321 "uniform myhalf3 DeferredColor_Diffuse;\n"
1322 "#ifdef USESPECULAR\n"
1323 "uniform myhalf3 DeferredColor_Specular;\n"
1324 "uniform myhalf SpecularPower;\n"
1328 " // calculate viewspace pixel position\n"
1330 " position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1331 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1332 " // decode viewspace pixel normal\n"
1333 " myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1334 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1335 " // surfacenormal = pixel normal in viewspace\n"
1336 " // LightVector = pixel to light in viewspace\n"
1337 " // CubeVector = position in lightspace\n"
1338 " // eyevector = pixel to view in viewspace\n"
1339 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1340 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1341 "#ifdef USEDIFFUSE\n"
1342 " // calculate diffuse shading\n"
1343 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1344 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1346 "#ifdef USESPECULAR\n"
1347 " // calculate directional shading\n"
1348 " vec3 eyevector = position * -1.0;\n"
1349 "# ifdef USEEXACTSPECULARMATH\n"
1350 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1352 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1353 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1357 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1358 " fade *= ShadowMapCompare(CubeVector);\n"
1361 "#ifdef USEDIFFUSE\n"
1362 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1364 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1366 "#ifdef USESPECULAR\n"
1367 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1369 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1372 "# ifdef USECUBEFILTER\n"
1373 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1374 " gl_FragData[0] *= cubecolor;\n"
1375 " gl_FragData[1] *= cubecolor;\n"
1378 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1379 "#ifdef USEDEFERREDLIGHTMAP\n"
1380 "uniform myhalf3 DeferredMod_Diffuse;\n"
1381 "uniform myhalf3 DeferredMod_Specular;\n"
1383 "uniform myhalf3 Color_Ambient;\n"
1384 "uniform myhalf3 Color_Diffuse;\n"
1385 "uniform myhalf3 Color_Specular;\n"
1386 "uniform myhalf SpecularPower;\n"
1388 "uniform myhalf3 Color_Glow;\n"
1390 "uniform myhalf Alpha;\n"
1391 "#ifdef USEREFLECTION\n"
1392 "uniform vec4 DistortScaleRefractReflect;\n"
1393 "uniform vec4 ScreenScaleRefractReflect;\n"
1394 "uniform vec4 ScreenCenterRefractReflect;\n"
1395 "uniform myhalf4 ReflectColor;\n"
1397 "#ifdef MODE_LIGHTDIRECTION\n"
1398 "uniform myhalf3 LightColor;\n"
1400 "#ifdef MODE_LIGHTSOURCE\n"
1401 "uniform myhalf3 LightColor;\n"
1405 "#ifdef USEOFFSETMAPPING\n"
1406 " // apply offsetmapping\n"
1407 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1408 "#define TexCoord TexCoordOffset\n"
1411 " // combine the diffuse textures (base, pants, shirt)\n"
1412 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1413 "#ifdef USEALPHAKILL\n"
1414 " if (color.a < 0.5)\n"
1417 " color.a *= Alpha;\n"
1418 "#ifdef USECOLORMAPPING\n"
1419 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1421 "#ifdef USEVERTEXTEXTUREBLEND\n"
1422 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1423 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1424 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1425 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1427 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1430 " // get the surface normal\n"
1431 "#ifdef USEVERTEXTEXTUREBLEND\n"
1432 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1434 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1437 " // get the material colors\n"
1438 " myhalf3 diffusetex = color.rgb;\n"
1439 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1440 "# ifdef USEVERTEXTEXTUREBLEND\n"
1441 " myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1443 " myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1450 "#ifdef MODE_LIGHTSOURCE\n"
1451 " // light source\n"
1452 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1453 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1454 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1455 "#ifdef USESPECULAR\n"
1456 "#ifdef USEEXACTSPECULARMATH\n"
1457 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1459 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1460 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1462 " color.rgb += glosstex * (specular * Color_Specular);\n"
1464 " color.rgb *= LightColor;\n"
1465 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1466 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1467 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1469 "# ifdef USECUBEFILTER\n"
1470 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1472 "#endif // MODE_LIGHTSOURCE\n"
1477 "#ifdef MODE_LIGHTDIRECTION\n"
1479 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1480 "#define lightcolor LightColor\n"
1481 "#endif // MODE_LIGHTDIRECTION\n"
1482 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1484 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1485 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1486 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1487 " // convert modelspace light vector to tangentspace\n"
1488 " myhalf3 lightnormal;\n"
1489 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1490 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1491 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1492 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1493 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1494 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1495 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1496 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1497 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1498 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1499 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1500 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1501 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1502 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1503 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1505 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1506 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1507 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1513 "#ifdef MODE_LIGHTMAP\n"
1514 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1515 "#endif // MODE_LIGHTMAP\n"
1516 "#ifdef MODE_VERTEXCOLOR\n"
1517 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1518 "#endif // MODE_VERTEXCOLOR\n"
1519 "#ifdef MODE_FLATCOLOR\n"
1520 " color.rgb = diffusetex * Color_Ambient;\n"
1521 "#endif // MODE_FLATCOLOR\n"
1527 "# ifdef USEDIFFUSE\n"
1528 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1529 "# ifdef USESPECULAR\n"
1530 "# ifdef USEEXACTSPECULARMATH\n"
1531 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1533 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1534 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1536 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1538 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1541 " color.rgb = diffusetex * Color_Ambient;\n"
1545 "#ifdef USEDEFERREDLIGHTMAP\n"
1546 " color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1547 " color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1551 "#ifdef USEVERTEXTEXTUREBLEND\n"
1552 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1554 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1559 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1562 " // 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"
1563 "#ifdef USEREFLECTION\n"
1564 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1565 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1566 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1567 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1568 " // FIXME temporary hack to detect the case that the reflection\n"
1569 " // gets blackened at edges due to leaving the area that contains actual\n"
1571 " // Remove this 'ack once we have a better way to stop this thing from\n"
1573 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1574 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1575 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1576 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1577 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1578 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1581 " gl_FragColor = vec4(color);\n"
1583 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1584 "#endif // !MODE_DEFERREDGEOMETRY\n"
1586 "#endif // FRAGMENT_SHADER\n"
1588 "#endif // !MODE_WATER\n"
1589 "#endif // !MODE_REFRACTION\n"
1590 "#endif // !MODE_BLOOMBLUR\n"
1591 "#endif // !MODE_GENERIC\n"
1592 "#endif // !MODE_POSTPROCESS\n"
1593 "#endif // !MODE_SHOWDEPTH\n"
1594 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1597 typedef struct shaderpermutationinfo_s
1599 const char *pretext;
1602 shaderpermutationinfo_t;
1604 typedef struct shadermodeinfo_s
1606 const char *vertexfilename;
1607 const char *geometryfilename;
1608 const char *fragmentfilename;
1609 const char *pretext;
1614 typedef enum shaderpermutation_e
1616 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1617 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1618 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1619 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1620 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1621 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1622 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1623 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1624 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1625 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1626 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1627 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1628 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1629 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1630 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1631 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1632 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1633 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1634 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1635 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1636 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1637 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1638 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1639 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1640 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1641 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
1642 SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
1643 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
1645 shaderpermutation_t;
1647 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1648 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1650 {"#define USEDIFFUSE\n", " diffuse"},
1651 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1652 {"#define USEVIEWTINT\n", " viewtint"},
1653 {"#define USECOLORMAPPING\n", " colormapping"},
1654 {"#define USESATURATION\n", " saturation"},
1655 {"#define USEFOGINSIDE\n", " foginside"},
1656 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1657 {"#define USEGAMMARAMPS\n", " gammaramps"},
1658 {"#define USECUBEFILTER\n", " cubefilter"},
1659 {"#define USEGLOW\n", " glow"},
1660 {"#define USEBLOOM\n", " bloom"},
1661 {"#define USESPECULAR\n", " specular"},
1662 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1663 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1664 {"#define USEREFLECTION\n", " reflection"},
1665 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1666 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1667 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1668 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1669 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1670 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1671 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1672 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1673 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1674 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1675 {"#define USEALPHAKILL\n", " alphakill"},
1678 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1679 typedef enum shadermode_e
1681 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1682 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1683 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1684 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1685 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1686 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1687 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1688 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1689 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1690 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1691 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1692 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1693 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1694 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1695 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1700 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1701 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1703 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1704 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1705 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1706 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1707 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1708 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1709 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1710 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1711 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1712 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1713 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1714 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1715 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1716 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1717 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1720 struct r_glsl_permutation_s;
1721 typedef struct r_glsl_permutation_s
1723 /// hash lookup data
1724 struct r_glsl_permutation_s *hashnext;
1726 unsigned int permutation;
1728 /// indicates if we have tried compiling this permutation already
1730 /// 0 if compilation failed
1732 /// locations of detected uniforms in program object, or -1 if not found
1733 int loc_Texture_First;
1734 int loc_Texture_Second;
1735 int loc_Texture_GammaRamps;
1736 int loc_Texture_Normal;
1737 int loc_Texture_Color;
1738 int loc_Texture_Gloss;
1739 int loc_Texture_Glow;
1740 int loc_Texture_SecondaryNormal;
1741 int loc_Texture_SecondaryColor;
1742 int loc_Texture_SecondaryGloss;
1743 int loc_Texture_SecondaryGlow;
1744 int loc_Texture_Pants;
1745 int loc_Texture_Shirt;
1746 int loc_Texture_FogMask;
1747 int loc_Texture_Lightmap;
1748 int loc_Texture_Deluxemap;
1749 int loc_Texture_Attenuation;
1750 int loc_Texture_Cube;
1751 int loc_Texture_Refraction;
1752 int loc_Texture_Reflection;
1753 int loc_Texture_ShadowMapRect;
1754 int loc_Texture_ShadowMapCube;
1755 int loc_Texture_ShadowMap2D;
1756 int loc_Texture_CubeProjection;
1757 int loc_Texture_ScreenDepth;
1758 int loc_Texture_ScreenNormalMap;
1759 int loc_Texture_ScreenDiffuse;
1760 int loc_Texture_ScreenSpecular;
1762 int loc_BloomBlur_Parameters;
1764 int loc_Color_Ambient;
1765 int loc_Color_Diffuse;
1766 int loc_Color_Specular;
1768 int loc_Color_Pants;
1769 int loc_Color_Shirt;
1770 int loc_DeferredColor_Ambient;
1771 int loc_DeferredColor_Diffuse;
1772 int loc_DeferredColor_Specular;
1773 int loc_DeferredMod_Diffuse;
1774 int loc_DeferredMod_Specular;
1775 int loc_DistortScaleRefractReflect;
1776 int loc_EyePosition;
1778 int loc_FogHeightFade;
1780 int loc_FogPlaneViewDist;
1781 int loc_FogRangeRecip;
1784 int loc_LightPosition;
1785 int loc_OffsetMapping_Scale;
1787 int loc_ReflectColor;
1788 int loc_ReflectFactor;
1789 int loc_ReflectOffset;
1790 int loc_RefractColor;
1792 int loc_ScreenCenterRefractReflect;
1793 int loc_ScreenScaleRefractReflect;
1794 int loc_ScreenToDepth;
1795 int loc_ShadowMap_Parameters;
1796 int loc_ShadowMap_TextureScale;
1797 int loc_SpecularPower;
1802 int loc_ViewTintColor;
1803 int loc_ViewToLight;
1805 r_glsl_permutation_t;
1807 #define SHADERPERMUTATION_HASHSIZE 256
1809 /// information about each possible shader permutation
1810 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1811 /// currently selected permutation
1812 r_glsl_permutation_t *r_glsl_permutation;
1813 /// storage for permutations linked in the hash table
1814 memexpandablearray_t r_glsl_permutationarray;
1816 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1818 //unsigned int hashdepth = 0;
1819 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1820 r_glsl_permutation_t *p;
1821 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1823 if (p->mode == mode && p->permutation == permutation)
1825 //if (hashdepth > 10)
1826 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1831 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1833 p->permutation = permutation;
1834 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1835 r_glsl_permutationhash[mode][hashindex] = p;
1836 //if (hashdepth > 10)
1837 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1841 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1844 if (!filename || !filename[0])
1846 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1849 if (printfromdisknotice)
1850 Con_DPrintf("from disk %s... ", filename);
1851 return shaderstring;
1853 else if (!strcmp(filename, "glsl/default.glsl"))
1855 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1856 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1858 return shaderstring;
1861 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1864 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1865 int vertstrings_count = 0;
1866 int geomstrings_count = 0;
1867 int fragstrings_count = 0;
1868 char *vertexstring, *geometrystring, *fragmentstring;
1869 const char *vertstrings_list[32+3];
1870 const char *geomstrings_list[32+3];
1871 const char *fragstrings_list[32+3];
1872 char permutationname[256];
1879 permutationname[0] = 0;
1880 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1881 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1882 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1884 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1886 // the first pretext is which type of shader to compile as
1887 // (later these will all be bound together as a program object)
1888 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1889 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1890 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1892 // the second pretext is the mode (for example a light source)
1893 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1894 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1895 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1896 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1898 // now add all the permutation pretexts
1899 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1901 if (permutation & (1<<i))
1903 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1904 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1905 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1906 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1910 // keep line numbers correct
1911 vertstrings_list[vertstrings_count++] = "\n";
1912 geomstrings_list[geomstrings_count++] = "\n";
1913 fragstrings_list[fragstrings_count++] = "\n";
1917 // now append the shader text itself
1918 vertstrings_list[vertstrings_count++] = vertexstring;
1919 geomstrings_list[geomstrings_count++] = geometrystring;
1920 fragstrings_list[fragstrings_count++] = fragmentstring;
1922 // if any sources were NULL, clear the respective list
1924 vertstrings_count = 0;
1925 if (!geometrystring)
1926 geomstrings_count = 0;
1927 if (!fragmentstring)
1928 fragstrings_count = 0;
1930 // compile the shader program
1931 if (vertstrings_count + geomstrings_count + fragstrings_count)
1932 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1936 qglUseProgramObjectARB(p->program);CHECKGLERROR
1937 // look up all the uniform variable names we care about, so we don't
1938 // have to look them up every time we set them
1940 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1941 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1942 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1943 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1944 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1945 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1946 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1947 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1948 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1949 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1950 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1951 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1952 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1953 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1954 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1955 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1956 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1957 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1958 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1959 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1960 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1961 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1962 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1963 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1964 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
1965 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
1966 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
1967 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
1968 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
1969 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
1970 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1971 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
1972 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
1973 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
1974 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
1975 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1976 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1977 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
1978 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
1979 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
1980 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
1981 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
1982 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1983 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1984 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1985 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
1986 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
1987 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
1988 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1989 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1990 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1991 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1992 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1993 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1994 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1995 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1996 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1997 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1998 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1999 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
2000 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2001 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2002 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2003 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2004 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
2005 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
2006 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
2007 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
2008 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
2009 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
2010 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
2011 // initialize the samplers to refer to the texture units we use
2012 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
2013 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
2014 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
2015 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
2016 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
2017 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
2018 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
2019 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2020 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2021 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2022 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
2023 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
2024 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
2025 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
2026 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
2027 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
2028 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
2029 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
2030 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
2031 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
2032 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
2033 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
2034 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
2035 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2036 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
2037 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2038 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
2039 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2041 if (developer.integer)
2042 Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2045 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
2049 Mem_Free(vertexstring);
2051 Mem_Free(geometrystring);
2053 Mem_Free(fragmentstring);
2056 void R_GLSL_Restart_f(void)
2058 unsigned int i, limit;
2059 r_glsl_permutation_t *p;
2060 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2061 for (i = 0;i < limit;i++)
2063 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2065 GL_Backend_FreeProgram(p->program);
2066 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2069 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2072 void R_GLSL_DumpShader_f(void)
2076 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2079 Con_Printf("failed to write to glsl/default.glsl\n");
2083 FS_Print(file, "/* The engine may define the following macros:\n");
2084 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2085 for (i = 0;i < SHADERMODE_COUNT;i++)
2086 FS_Print(file, shadermodeinfo[i].pretext);
2087 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2088 FS_Print(file, shaderpermutationinfo[i].pretext);
2089 FS_Print(file, "*/\n");
2090 FS_Print(file, builtinshaderstring);
2093 Con_Printf("glsl/default.glsl written\n");
2096 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
2098 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2099 if (r_glsl_permutation != perm)
2101 r_glsl_permutation = perm;
2102 if (!r_glsl_permutation->program)
2104 if (!r_glsl_permutation->compiled)
2105 R_GLSL_CompilePermutation(perm, mode, permutation);
2106 if (!r_glsl_permutation->program)
2108 // remove features until we find a valid permutation
2110 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2112 // reduce i more quickly whenever it would not remove any bits
2113 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2114 if (!(permutation & j))
2117 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2118 if (!r_glsl_permutation->compiled)
2119 R_GLSL_CompilePermutation(perm, mode, permutation);
2120 if (r_glsl_permutation->program)
2123 if (i >= SHADERPERMUTATION_COUNT)
2125 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2126 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2127 qglUseProgramObjectARB(0);CHECKGLERROR
2128 return; // no bit left to clear, entire mode is broken
2133 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2137 void R_SetupGenericShader(qboolean usetexture)
2139 switch(vid.renderpath)
2141 case RENDERPATH_GL20:
2142 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2144 case RENDERPATH_GL13:
2145 case RENDERPATH_GL11:
2150 void R_SetupGenericTwoTextureShader(int texturemode)
2152 switch (vid.renderpath)
2154 case RENDERPATH_GL20:
2155 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))));
2157 case RENDERPATH_GL13:
2158 case RENDERPATH_GL11:
2159 R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
2164 void R_SetupDepthOrShadowShader(void)
2166 switch (vid.renderpath)
2168 case RENDERPATH_GL20:
2169 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2171 case RENDERPATH_GL13:
2173 case RENDERPATH_GL11:
2178 void R_SetupShowDepthShader(void)
2180 switch (vid.renderpath)
2182 case RENDERPATH_GL20:
2183 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2185 case RENDERPATH_GL13:
2187 case RENDERPATH_GL11:
2192 extern qboolean r_shadow_usingdeferredprepass;
2193 extern cvar_t r_shadow_deferred_8bitrange;
2194 extern rtexture_t *r_shadow_attenuationgradienttexture;
2195 extern rtexture_t *r_shadow_attenuation2dtexture;
2196 extern rtexture_t *r_shadow_attenuation3dtexture;
2197 extern qboolean r_shadow_usingshadowmaprect;
2198 extern qboolean r_shadow_usingshadowmapcube;
2199 extern qboolean r_shadow_usingshadowmap2d;
2200 extern float r_shadow_shadowmap_texturescale[2];
2201 extern float r_shadow_shadowmap_parameters[4];
2202 extern qboolean r_shadow_shadowmapvsdct;
2203 extern qboolean r_shadow_shadowmapsampler;
2204 extern int r_shadow_shadowmappcf;
2205 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2207 // select a permutation of the lighting shader appropriate to this
2208 // combination of texture, entity, light source, and fogging, only use the
2209 // minimum features necessary to avoid wasting rendering time in the
2210 // fragment shader on features that are not being used
2211 unsigned int permutation = 0;
2212 unsigned int mode = 0;
2213 // TODO: implement geometry-shader based shadow volumes someday
2214 if (r_glsl_offsetmapping.integer)
2216 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2217 if (r_glsl_offsetmapping_reliefmapping.integer)
2218 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2220 if (rsurfacepass == RSURFPASS_BACKGROUND)
2222 // distorted background
2223 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2224 mode = SHADERMODE_WATER;
2226 mode = SHADERMODE_REFRACTION;
2228 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2230 // normalmap (deferred prepass), may use alpha test on diffuse
2231 mode = SHADERMODE_DEFERREDGEOMETRY;
2232 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2233 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2234 if (r_glsl_offsetmapping.integer)
2236 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2237 if (r_glsl_offsetmapping_reliefmapping.integer)
2238 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2241 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2244 mode = SHADERMODE_LIGHTSOURCE;
2245 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2246 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2247 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2248 permutation |= SHADERPERMUTATION_CUBEFILTER;
2249 if (diffusescale > 0)
2250 permutation |= SHADERPERMUTATION_DIFFUSE;
2251 if (specularscale > 0)
2252 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2253 if (r_refdef.fogenabled)
2254 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2255 if (rsurface.texture->colormapping)
2256 permutation |= SHADERPERMUTATION_COLORMAPPING;
2257 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2259 if (r_shadow_usingshadowmaprect)
2260 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2261 if (r_shadow_usingshadowmap2d)
2262 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2263 if (r_shadow_usingshadowmapcube)
2264 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2265 else if(r_shadow_shadowmapvsdct)
2266 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2268 if (r_shadow_shadowmapsampler)
2269 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2270 if (r_shadow_shadowmappcf > 1)
2271 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2272 else if (r_shadow_shadowmappcf)
2273 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2276 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2278 // unshaded geometry (fullbright or ambient model lighting)
2279 mode = SHADERMODE_FLATCOLOR;
2280 ambientscale = diffusescale = specularscale = 0;
2281 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2282 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2283 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2284 permutation |= SHADERPERMUTATION_GLOW;
2285 if (r_refdef.fogenabled)
2286 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2287 if (rsurface.texture->colormapping)
2288 permutation |= SHADERPERMUTATION_COLORMAPPING;
2289 if (r_glsl_offsetmapping.integer)
2291 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2292 if (r_glsl_offsetmapping_reliefmapping.integer)
2293 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2295 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2296 permutation |= SHADERPERMUTATION_REFLECTION;
2298 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2300 // directional model lighting
2301 mode = SHADERMODE_LIGHTDIRECTION;
2302 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2303 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2304 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2305 permutation |= SHADERPERMUTATION_GLOW;
2306 permutation |= SHADERPERMUTATION_DIFFUSE;
2307 if (specularscale > 0)
2308 permutation |= SHADERPERMUTATION_SPECULAR;
2309 if (r_refdef.fogenabled)
2310 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2311 if (rsurface.texture->colormapping)
2312 permutation |= SHADERPERMUTATION_COLORMAPPING;
2313 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2314 permutation |= SHADERPERMUTATION_REFLECTION;
2315 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2316 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2318 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2320 // ambient model lighting
2321 mode = SHADERMODE_LIGHTDIRECTION;
2322 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2323 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2324 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2325 permutation |= SHADERPERMUTATION_GLOW;
2326 if (r_refdef.fogenabled)
2327 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2328 if (rsurface.texture->colormapping)
2329 permutation |= SHADERPERMUTATION_COLORMAPPING;
2330 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2331 permutation |= SHADERPERMUTATION_REFLECTION;
2332 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2333 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2338 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2340 // deluxemapping (light direction texture)
2341 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2342 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2344 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2345 permutation |= SHADERPERMUTATION_DIFFUSE;
2346 if (specularscale > 0)
2347 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2349 else if (r_glsl_deluxemapping.integer >= 2)
2351 // fake deluxemapping (uniform light direction in tangentspace)
2352 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2353 permutation |= SHADERPERMUTATION_DIFFUSE;
2354 if (specularscale > 0)
2355 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2357 else if (rsurface.uselightmaptexture)
2359 // ordinary lightmapping (q1bsp, q3bsp)
2360 mode = SHADERMODE_LIGHTMAP;
2364 // ordinary vertex coloring (q3bsp)
2365 mode = SHADERMODE_VERTEXCOLOR;
2367 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2368 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2369 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2370 permutation |= SHADERPERMUTATION_GLOW;
2371 if (r_refdef.fogenabled)
2372 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2373 if (rsurface.texture->colormapping)
2374 permutation |= SHADERPERMUTATION_COLORMAPPING;
2375 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376 permutation |= SHADERPERMUTATION_REFLECTION;
2377 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2378 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2380 if(permutation & SHADERPERMUTATION_SPECULAR)
2381 if(r_shadow_glossexact.integer)
2382 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2383 if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
2384 permutation |= SHADERPERMUTATION_ALPHAKILL;
2385 R_SetupShader_SetPermutation(mode, permutation);
2386 if (mode == SHADERMODE_LIGHTSOURCE)
2388 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2389 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2390 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
2391 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
2392 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
2394 // additive passes are only darkened by fog, not tinted
2395 if (r_glsl_permutation->loc_FogColor >= 0)
2396 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2397 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]);
2398 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]);
2399 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2403 if (mode == SHADERMODE_FLATCOLOR)
2405 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
2407 else if (mode == SHADERMODE_LIGHTDIRECTION)
2409 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
2410 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
2411 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
2412 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
2413 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2414 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2415 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]);
2419 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
2420 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2421 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
2422 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2423 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2425 // additive passes are only darkened by fog, not tinted
2426 if (r_glsl_permutation->loc_FogColor >= 0)
2428 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2429 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2431 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2433 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);
2434 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]);
2435 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]);
2436 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2437 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2438 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2439 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2440 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2442 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2443 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
2444 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2445 if (r_glsl_permutation->loc_Color_Pants >= 0)
2447 if (rsurface.texture->currentskinframe->pants)
2448 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2450 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2452 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2454 if (rsurface.texture->currentskinframe->shirt)
2455 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2457 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2459 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2460 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2461 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2462 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2463 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2464 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2468 void R_SetupDeferredLightShader(const rtlight_t *rtlight)
2470 // select a permutation of the lighting shader appropriate to this
2471 // combination of texture, entity, light source, and fogging, only use the
2472 // minimum features necessary to avoid wasting rendering time in the
2473 // fragment shader on features that are not being used
2474 unsigned int permutation = 0;
2475 unsigned int mode = 0;
2476 const float *lightcolorbase = rtlight->currentcolor;
2477 float ambientscale = rtlight->ambientscale;
2478 float diffusescale = rtlight->diffusescale;
2479 float specularscale = rtlight->specularscale;
2480 // this is the location of the light in view space
2481 vec3_t viewlightorigin;
2482 // this transforms from view space (camera) to light space (cubemap)
2483 matrix4x4_t viewtolight;
2484 matrix4x4_t lighttoview;
2485 float viewtolight16f[16];
2486 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2488 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2489 if (rtlight->currentcubemap != r_texture_whitecube)
2490 permutation |= SHADERPERMUTATION_CUBEFILTER;
2491 if (diffusescale > 0)
2492 permutation |= SHADERPERMUTATION_DIFFUSE;
2493 if (specularscale > 0)
2495 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2496 if (r_shadow_glossexact.integer)
2497 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2499 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2501 if (r_shadow_usingshadowmaprect)
2502 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2503 if (r_shadow_usingshadowmap2d)
2504 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2505 if (r_shadow_usingshadowmapcube)
2506 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2507 else if(r_shadow_shadowmapvsdct)
2508 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2510 if (r_shadow_shadowmapsampler)
2511 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2512 if (r_shadow_shadowmappcf > 1)
2513 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2514 else if (r_shadow_shadowmappcf)
2515 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2517 R_SetupShader_SetPermutation(mode, permutation);
2518 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2519 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2520 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2521 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2522 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2523 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight, 1, false, viewtolight16f);
2524 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2525 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2526 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2527 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]);
2528 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]);
2529 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2530 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2533 #define SKINFRAME_HASH 1024
2537 int loadsequence; // incremented each level change
2538 memexpandablearray_t array;
2539 skinframe_t *hash[SKINFRAME_HASH];
2542 r_skinframe_t r_skinframe;
2544 void R_SkinFrame_PrepareForPurge(void)
2546 r_skinframe.loadsequence++;
2547 // wrap it without hitting zero
2548 if (r_skinframe.loadsequence >= 200)
2549 r_skinframe.loadsequence = 1;
2552 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2556 // mark the skinframe as used for the purging code
2557 skinframe->loadsequence = r_skinframe.loadsequence;
2560 void R_SkinFrame_Purge(void)
2564 for (i = 0;i < SKINFRAME_HASH;i++)
2566 for (s = r_skinframe.hash[i];s;s = s->next)
2568 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2570 if (s->merged == s->base)
2572 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2573 R_PurgeTexture(s->stain );s->stain = NULL;
2574 R_PurgeTexture(s->merged);s->merged = NULL;
2575 R_PurgeTexture(s->base );s->base = NULL;
2576 R_PurgeTexture(s->pants );s->pants = NULL;
2577 R_PurgeTexture(s->shirt );s->shirt = NULL;
2578 R_PurgeTexture(s->nmap );s->nmap = NULL;
2579 R_PurgeTexture(s->gloss );s->gloss = NULL;
2580 R_PurgeTexture(s->glow );s->glow = NULL;
2581 R_PurgeTexture(s->fog );s->fog = NULL;
2582 s->loadsequence = 0;
2588 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2590 char basename[MAX_QPATH];
2592 Image_StripImageExtension(name, basename, sizeof(basename));
2594 if( last == NULL ) {
2596 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2597 item = r_skinframe.hash[hashindex];
2602 // linearly search through the hash bucket
2603 for( ; item ; item = item->next ) {
2604 if( !strcmp( item->basename, basename ) ) {
2611 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2615 char basename[MAX_QPATH];
2617 Image_StripImageExtension(name, basename, sizeof(basename));
2619 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2620 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2621 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2625 rtexture_t *dyntexture;
2626 // check whether its a dynamic texture
2627 dyntexture = CL_GetDynTexture( basename );
2628 if (!add && !dyntexture)
2630 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2631 memset(item, 0, sizeof(*item));
2632 strlcpy(item->basename, basename, sizeof(item->basename));
2633 item->base = dyntexture; // either NULL or dyntexture handle
2634 item->textureflags = textureflags;
2635 item->comparewidth = comparewidth;
2636 item->compareheight = compareheight;
2637 item->comparecrc = comparecrc;
2638 item->next = r_skinframe.hash[hashindex];
2639 r_skinframe.hash[hashindex] = item;
2641 else if( item->base == NULL )
2643 rtexture_t *dyntexture;
2644 // check whether its a dynamic texture
2645 // 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]
2646 dyntexture = CL_GetDynTexture( basename );
2647 item->base = dyntexture; // either NULL or dyntexture handle
2650 R_SkinFrame_MarkUsed(item);
2654 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2656 unsigned long long avgcolor[5], wsum; \
2664 for(pix = 0; pix < cnt; ++pix) \
2667 for(comp = 0; comp < 3; ++comp) \
2669 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2672 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2674 for(comp = 0; comp < 3; ++comp) \
2675 avgcolor[comp] += getpixel * w; \
2678 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2679 avgcolor[4] += getpixel; \
2681 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2683 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2684 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2685 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2686 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2689 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2692 unsigned char *pixels;
2693 unsigned char *bumppixels;
2694 unsigned char *basepixels = NULL;
2695 int basepixels_width;
2696 int basepixels_height;
2697 skinframe_t *skinframe;
2699 if (cls.state == ca_dedicated)
2702 // return an existing skinframe if already loaded
2703 // if loading of the first image fails, don't make a new skinframe as it
2704 // would cause all future lookups of this to be missing
2705 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2706 if (skinframe && skinframe->base)
2709 basepixels = loadimagepixelsbgra(name, complain, true);
2710 if (basepixels == NULL)
2713 if (developer_loading.integer)
2714 Con_Printf("loading skin \"%s\"\n", name);
2716 // we've got some pixels to store, so really allocate this new texture now
2718 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2719 skinframe->stain = NULL;
2720 skinframe->merged = NULL;
2721 skinframe->base = r_texture_notexture;
2722 skinframe->pants = NULL;
2723 skinframe->shirt = NULL;
2724 skinframe->nmap = r_texture_blanknormalmap;
2725 skinframe->gloss = NULL;
2726 skinframe->glow = NULL;
2727 skinframe->fog = NULL;
2728 skinframe->hasalpha = false;
2730 basepixels_width = image_width;
2731 basepixels_height = image_height;
2732 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);
2734 if (textureflags & TEXF_ALPHA)
2736 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2738 if (basepixels[j] < 255)
2740 skinframe->hasalpha = true;
2744 if (r_loadfog && skinframe->hasalpha)
2746 // has transparent pixels
2747 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2748 for (j = 0;j < image_width * image_height * 4;j += 4)
2753 pixels[j+3] = basepixels[j+3];
2755 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);
2760 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2761 //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]);
2763 // _norm is the name used by tenebrae and has been adopted as standard
2764 if (r_loadnormalmap)
2766 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2768 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);
2772 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2774 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2775 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2776 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);
2778 Mem_Free(bumppixels);
2780 else if (r_shadow_bumpscale_basetexture.value > 0)
2782 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2783 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2784 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);
2788 // _luma is supported for tenebrae compatibility
2789 // (I think it's a very stupid name, but oh well)
2790 // _glow is the preferred name
2791 if ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))) {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;}
2792 if (r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false))) {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;}
2793 if ((pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false))) {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;}
2794 if ((pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false))) {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;}
2797 Mem_Free(basepixels);
2802 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2803 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2806 unsigned char *temp1, *temp2;
2807 skinframe_t *skinframe;
2809 if (cls.state == ca_dedicated)
2812 // if already loaded just return it, otherwise make a new skinframe
2813 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2814 if (skinframe && skinframe->base)
2817 skinframe->stain = NULL;
2818 skinframe->merged = NULL;
2819 skinframe->base = r_texture_notexture;
2820 skinframe->pants = NULL;
2821 skinframe->shirt = NULL;
2822 skinframe->nmap = r_texture_blanknormalmap;
2823 skinframe->gloss = NULL;
2824 skinframe->glow = NULL;
2825 skinframe->fog = NULL;
2826 skinframe->hasalpha = false;
2828 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2832 if (developer_loading.integer)
2833 Con_Printf("loading 32bit skin \"%s\"\n", name);
2835 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2837 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2838 temp2 = temp1 + width * height * 4;
2839 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2840 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2843 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2844 if (textureflags & TEXF_ALPHA)
2846 for (i = 3;i < width * height * 4;i += 4)
2848 if (skindata[i] < 255)
2850 skinframe->hasalpha = true;
2854 if (r_loadfog && skinframe->hasalpha)
2856 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2857 memcpy(fogpixels, skindata, width * height * 4);
2858 for (i = 0;i < width * height * 4;i += 4)
2859 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2860 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2861 Mem_Free(fogpixels);
2865 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2866 //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]);
2871 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2875 skinframe_t *skinframe;
2877 if (cls.state == ca_dedicated)
2880 // if already loaded just return it, otherwise make a new skinframe
2881 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2882 if (skinframe && skinframe->base)
2885 skinframe->stain = NULL;
2886 skinframe->merged = NULL;
2887 skinframe->base = r_texture_notexture;
2888 skinframe->pants = NULL;
2889 skinframe->shirt = NULL;
2890 skinframe->nmap = r_texture_blanknormalmap;
2891 skinframe->gloss = NULL;
2892 skinframe->glow = NULL;
2893 skinframe->fog = NULL;
2894 skinframe->hasalpha = false;
2896 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2900 if (developer_loading.integer)
2901 Con_Printf("loading quake skin \"%s\"\n", name);
2903 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
2904 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
2905 memcpy(skinframe->qpixels, skindata, width*height);
2906 skinframe->qwidth = width;
2907 skinframe->qheight = height;
2910 for (i = 0;i < width * height;i++)
2911 featuresmask |= palette_featureflags[skindata[i]];
2913 skinframe->hasalpha = false;
2914 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2915 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2916 skinframe->qgeneratemerged = true;
2917 skinframe->qgeneratebase = skinframe->qhascolormapping;
2918 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2920 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2921 //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]);
2926 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2930 unsigned char *skindata;
2932 if (!skinframe->qpixels)
2935 if (!skinframe->qhascolormapping)
2936 colormapped = false;
2940 if (!skinframe->qgeneratebase)
2945 if (!skinframe->qgeneratemerged)
2949 width = skinframe->qwidth;
2950 height = skinframe->qheight;
2951 skindata = skinframe->qpixels;
2953 if (skinframe->qgeneratenmap)
2955 unsigned char *temp1, *temp2;
2956 skinframe->qgeneratenmap = false;
2957 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2958 temp2 = temp1 + width * height * 4;
2959 // use either a custom palette or the quake palette
2960 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2961 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2962 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2966 if (skinframe->qgenerateglow)
2968 skinframe->qgenerateglow = false;
2969 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
2974 skinframe->qgeneratebase = false;
2975 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
2976 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
2977 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
2981 skinframe->qgeneratemerged = false;
2982 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
2985 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
2987 Mem_Free(skinframe->qpixels);
2988 skinframe->qpixels = NULL;
2992 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
2995 skinframe_t *skinframe;
2997 if (cls.state == ca_dedicated)
3000 // if already loaded just return it, otherwise make a new skinframe
3001 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3002 if (skinframe && skinframe->base)
3005 skinframe->stain = NULL;
3006 skinframe->merged = NULL;
3007 skinframe->base = r_texture_notexture;
3008 skinframe->pants = NULL;
3009 skinframe->shirt = NULL;
3010 skinframe->nmap = r_texture_blanknormalmap;
3011 skinframe->gloss = NULL;
3012 skinframe->glow = NULL;
3013 skinframe->fog = NULL;
3014 skinframe->hasalpha = false;
3016 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3020 if (developer_loading.integer)
3021 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3023 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3024 if (textureflags & TEXF_ALPHA)
3026 for (i = 0;i < width * height;i++)
3028 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3030 skinframe->hasalpha = true;
3034 if (r_loadfog && skinframe->hasalpha)
3035 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3038 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3039 //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]);
3044 skinframe_t *R_SkinFrame_LoadMissing(void)
3046 skinframe_t *skinframe;
3048 if (cls.state == ca_dedicated)
3051 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
3052 skinframe->stain = NULL;
3053 skinframe->merged = NULL;
3054 skinframe->base = r_texture_notexture;
3055 skinframe->pants = NULL;
3056 skinframe->shirt = NULL;
3057 skinframe->nmap = r_texture_blanknormalmap;
3058 skinframe->gloss = NULL;
3059 skinframe->glow = NULL;
3060 skinframe->fog = NULL;
3061 skinframe->hasalpha = false;
3063 skinframe->avgcolor[0] = rand() / RAND_MAX;
3064 skinframe->avgcolor[1] = rand() / RAND_MAX;
3065 skinframe->avgcolor[2] = rand() / RAND_MAX;
3066 skinframe->avgcolor[3] = 1;
3071 void R_Main_FreeViewCache(void)
3073 if (r_refdef.viewcache.entityvisible)
3074 Mem_Free(r_refdef.viewcache.entityvisible);
3075 if (r_refdef.viewcache.world_pvsbits)
3076 Mem_Free(r_refdef.viewcache.world_pvsbits);
3077 if (r_refdef.viewcache.world_leafvisible)
3078 Mem_Free(r_refdef.viewcache.world_leafvisible);
3079 if (r_refdef.viewcache.world_surfacevisible)
3080 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3081 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3084 void R_Main_ResizeViewCache(void)
3086 int numentities = r_refdef.scene.numentities;
3087 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3088 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3089 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3090 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3091 if (r_refdef.viewcache.maxentities < numentities)
3093 r_refdef.viewcache.maxentities = numentities;
3094 if (r_refdef.viewcache.entityvisible)
3095 Mem_Free(r_refdef.viewcache.entityvisible);
3096 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3098 if (r_refdef.viewcache.world_numclusters != numclusters)
3100 r_refdef.viewcache.world_numclusters = numclusters;
3101 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3102 if (r_refdef.viewcache.world_pvsbits)
3103 Mem_Free(r_refdef.viewcache.world_pvsbits);
3104 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3106 if (r_refdef.viewcache.world_numleafs != numleafs)
3108 r_refdef.viewcache.world_numleafs = numleafs;
3109 if (r_refdef.viewcache.world_leafvisible)
3110 Mem_Free(r_refdef.viewcache.world_leafvisible);
3111 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3113 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3115 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3116 if (r_refdef.viewcache.world_surfacevisible)
3117 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3118 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3122 extern rtexture_t *loadingscreentexture;
3123 void gl_main_start(void)
3125 loadingscreentexture = NULL;
3126 r_texture_blanknormalmap = NULL;
3127 r_texture_white = NULL;
3128 r_texture_grey128 = NULL;
3129 r_texture_black = NULL;
3130 r_texture_whitecube = NULL;
3131 r_texture_normalizationcube = NULL;
3132 r_texture_fogattenuation = NULL;
3133 r_texture_gammaramps = NULL;
3135 switch(vid.renderpath)
3137 case RENDERPATH_GL20:
3138 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3139 Cvar_SetValueQuick(&gl_combine, 1);
3140 Cvar_SetValueQuick(&r_glsl, 1);
3141 r_loadnormalmap = true;
3145 case RENDERPATH_GL13:
3146 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3147 Cvar_SetValueQuick(&gl_combine, 1);
3148 Cvar_SetValueQuick(&r_glsl, 0);
3149 r_loadnormalmap = false;
3150 r_loadgloss = false;
3153 case RENDERPATH_GL11:
3154 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3155 Cvar_SetValueQuick(&gl_combine, 0);
3156 Cvar_SetValueQuick(&r_glsl, 0);
3157 r_loadnormalmap = false;
3158 r_loadgloss = false;
3164 R_FrameData_Reset();
3168 memset(r_queries, 0, sizeof(r_queries));
3170 r_qwskincache = NULL;
3171 r_qwskincache_size = 0;
3173 // set up r_skinframe loading system for textures
3174 memset(&r_skinframe, 0, sizeof(r_skinframe));
3175 r_skinframe.loadsequence = 1;
3176 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3178 r_main_texturepool = R_AllocTexturePool();
3179 R_BuildBlankTextures();
3181 if (vid.support.arb_texture_cube_map)
3184 R_BuildNormalizationCube();
3186 r_texture_fogattenuation = NULL;
3187 r_texture_gammaramps = NULL;
3188 //r_texture_fogintensity = NULL;
3189 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3190 memset(&r_waterstate, 0, sizeof(r_waterstate));
3191 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3192 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3193 memset(&r_svbsp, 0, sizeof (r_svbsp));
3195 r_refdef.fogmasktable_density = 0;
3198 void gl_main_shutdown(void)
3201 R_FrameData_Reset();
3203 R_Main_FreeViewCache();
3206 qglDeleteQueriesARB(r_maxqueries, r_queries);
3210 memset(r_queries, 0, sizeof(r_queries));
3212 r_qwskincache = NULL;
3213 r_qwskincache_size = 0;
3215 // clear out the r_skinframe state
3216 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3217 memset(&r_skinframe, 0, sizeof(r_skinframe));
3220 Mem_Free(r_svbsp.nodes);
3221 memset(&r_svbsp, 0, sizeof (r_svbsp));
3222 R_FreeTexturePool(&r_main_texturepool);
3223 loadingscreentexture = NULL;
3224 r_texture_blanknormalmap = NULL;
3225 r_texture_white = NULL;
3226 r_texture_grey128 = NULL;
3227 r_texture_black = NULL;
3228 r_texture_whitecube = NULL;
3229 r_texture_normalizationcube = NULL;
3230 r_texture_fogattenuation = NULL;
3231 r_texture_gammaramps = NULL;
3232 //r_texture_fogintensity = NULL;
3233 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3234 memset(&r_waterstate, 0, sizeof(r_waterstate));
3238 extern void CL_ParseEntityLump(char *entitystring);
3239 void gl_main_newmap(void)
3241 // FIXME: move this code to client
3243 char *entities, entname[MAX_QPATH];
3245 Mem_Free(r_qwskincache);
3246 r_qwskincache = NULL;
3247 r_qwskincache_size = 0;
3250 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
3251 l = (int)strlen(entname) - 4;
3252 if (l >= 0 && !strcmp(entname + l, ".bsp"))
3254 memcpy(entname + l, ".ent", 5);
3255 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3257 CL_ParseEntityLump(entities);
3262 if (cl.worldmodel->brush.entities)
3263 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3265 R_Main_FreeViewCache();
3267 R_FrameData_Reset();
3270 void GL_Main_Init(void)
3272 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3274 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3275 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3276 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3277 if (gamemode == GAME_NEHAHRA)
3279 Cvar_RegisterVariable (&gl_fogenable);
3280 Cvar_RegisterVariable (&gl_fogdensity);
3281 Cvar_RegisterVariable (&gl_fogred);
3282 Cvar_RegisterVariable (&gl_foggreen);
3283 Cvar_RegisterVariable (&gl_fogblue);
3284 Cvar_RegisterVariable (&gl_fogstart);
3285 Cvar_RegisterVariable (&gl_fogend);
3286 Cvar_RegisterVariable (&gl_skyclip);
3288 Cvar_RegisterVariable(&r_motionblur);
3289 Cvar_RegisterVariable(&r_motionblur_maxblur);
3290 Cvar_RegisterVariable(&r_motionblur_bmin);
3291 Cvar_RegisterVariable(&r_motionblur_vmin);
3292 Cvar_RegisterVariable(&r_motionblur_vmax);
3293 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3294 Cvar_RegisterVariable(&r_motionblur_randomize);
3295 Cvar_RegisterVariable(&r_damageblur);
3296 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3297 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3298 Cvar_RegisterVariable(&r_equalize_entities_by);
3299 Cvar_RegisterVariable(&r_equalize_entities_to);
3300 Cvar_RegisterVariable(&r_depthfirst);
3301 Cvar_RegisterVariable(&r_useinfinitefarclip);
3302 Cvar_RegisterVariable(&r_farclip_base);
3303 Cvar_RegisterVariable(&r_farclip_world);
3304 Cvar_RegisterVariable(&r_nearclip);
3305 Cvar_RegisterVariable(&r_showbboxes);
3306 Cvar_RegisterVariable(&r_showsurfaces);
3307 Cvar_RegisterVariable(&r_showtris);
3308 Cvar_RegisterVariable(&r_shownormals);
3309 Cvar_RegisterVariable(&r_showlighting);
3310 Cvar_RegisterVariable(&r_showshadowvolumes);
3311 Cvar_RegisterVariable(&r_showcollisionbrushes);
3312 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3313 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3314 Cvar_RegisterVariable(&r_showdisabledepthtest);
3315 Cvar_RegisterVariable(&r_drawportals);
3316 Cvar_RegisterVariable(&r_drawentities);
3317 Cvar_RegisterVariable(&r_cullentities_trace);
3318 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3319 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3320 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3321 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3322 Cvar_RegisterVariable(&r_drawviewmodel);
3323 Cvar_RegisterVariable(&r_speeds);
3324 Cvar_RegisterVariable(&r_fullbrights);
3325 Cvar_RegisterVariable(&r_wateralpha);
3326 Cvar_RegisterVariable(&r_dynamic);
3327 Cvar_RegisterVariable(&r_fullbright);
3328 Cvar_RegisterVariable(&r_shadows);
3329 Cvar_RegisterVariable(&r_shadows_darken);
3330 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3331 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3332 Cvar_RegisterVariable(&r_shadows_throwdistance);
3333 Cvar_RegisterVariable(&r_shadows_throwdirection);
3334 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3335 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3336 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3337 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3338 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3339 Cvar_RegisterVariable(&r_fog_exp2);
3340 Cvar_RegisterVariable(&r_drawfog);
3341 Cvar_RegisterVariable(&r_transparentdepthmasking);
3342 Cvar_RegisterVariable(&r_textureunits);
3343 Cvar_RegisterVariable(&gl_combine);
3344 Cvar_RegisterVariable(&r_glsl);
3345 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3346 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3347 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3348 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3349 Cvar_RegisterVariable(&r_glsl_postprocess);
3350 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3351 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3352 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3353 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3354 Cvar_RegisterVariable(&r_water);
3355 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3356 Cvar_RegisterVariable(&r_water_clippingplanebias);
3357 Cvar_RegisterVariable(&r_water_refractdistort);
3358 Cvar_RegisterVariable(&r_water_reflectdistort);
3359 Cvar_RegisterVariable(&r_lerpsprites);
3360 Cvar_RegisterVariable(&r_lerpmodels);
3361 Cvar_RegisterVariable(&r_lerplightstyles);
3362 Cvar_RegisterVariable(&r_waterscroll);
3363 Cvar_RegisterVariable(&r_bloom);
3364 Cvar_RegisterVariable(&r_bloom_colorscale);
3365 Cvar_RegisterVariable(&r_bloom_brighten);
3366 Cvar_RegisterVariable(&r_bloom_blur);
3367 Cvar_RegisterVariable(&r_bloom_resolution);
3368 Cvar_RegisterVariable(&r_bloom_colorexponent);
3369 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3370 Cvar_RegisterVariable(&r_hdr);
3371 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3372 Cvar_RegisterVariable(&r_hdr_glowintensity);
3373 Cvar_RegisterVariable(&r_hdr_range);
3374 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3375 Cvar_RegisterVariable(&developer_texturelogging);
3376 Cvar_RegisterVariable(&gl_lightmaps);
3377 Cvar_RegisterVariable(&r_test);
3378 Cvar_RegisterVariable(&r_batchmode);
3379 Cvar_RegisterVariable(&r_glsl_saturation);
3380 Cvar_RegisterVariable(&r_framedatasize);
3381 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3382 Cvar_SetValue("r_fullbrights", 0);
3383 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3385 Cvar_RegisterVariable(&r_track_sprites);
3386 Cvar_RegisterVariable(&r_track_sprites_flags);
3387 Cvar_RegisterVariable(&r_track_sprites_scalew);
3388 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3391 extern void R_Textures_Init(void);
3392 extern void GL_Draw_Init(void);
3393 extern void GL_Main_Init(void);
3394 extern void R_Shadow_Init(void);
3395 extern void R_Sky_Init(void);
3396 extern void GL_Surf_Init(void);
3397 extern void R_Particles_Init(void);
3398 extern void R_Explosion_Init(void);
3399 extern void gl_backend_init(void);
3400 extern void Sbar_Init(void);
3401 extern void R_LightningBeams_Init(void);
3402 extern void Mod_RenderInit(void);
3404 void Render_Init(void)
3416 R_LightningBeams_Init();
3425 extern char *ENGINE_EXTENSIONS;
3428 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3429 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3430 gl_version = (const char *)qglGetString(GL_VERSION);
3431 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3435 if (!gl_platformextensions)
3436 gl_platformextensions = "";
3438 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3439 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3440 Con_Printf("GL_VERSION: %s\n", gl_version);
3441 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3442 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3444 VID_CheckExtensions();
3446 // LordHavoc: report supported extensions
3447 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3449 // clear to black (loading plaque will be seen over this)
3451 qglClearColor(0,0,0,1);CHECKGLERROR
3452 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3455 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3459 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3461 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3464 p = r_refdef.view.frustum + i;
3469 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3473 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3477 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3481 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3485 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3489 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3493 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3497 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3505 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3509 for (i = 0;i < numplanes;i++)
3516 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3520 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3524 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3528 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3532 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3536 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3540 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3544 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3552 //==================================================================================
3554 // LordHavoc: this stores temporary data used within the same frame
3556 qboolean r_framedata_failed;
3557 static size_t r_framedata_size;
3558 static size_t r_framedata_current;
3559 static void *r_framedata_base;
3561 void R_FrameData_Reset(void)
3563 if (r_framedata_base);
3564 Mem_Free(r_framedata_base);
3565 r_framedata_base = NULL;
3566 r_framedata_size = 0;
3567 r_framedata_current = 0;
3568 r_framedata_failed = false;
3571 void R_FrameData_NewFrame(void)
3574 if (r_framedata_failed)
3575 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
3576 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
3577 wantedsize = bound(65536, wantedsize, 128*1024*1024);
3578 if (r_framedata_size != wantedsize)
3580 r_framedata_size = wantedsize;
3581 if (r_framedata_base);
3582 Mem_Free(r_framedata_base);
3583 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
3585 r_framedata_current = 0;
3586 r_framedata_failed = false;
3589 void *R_FrameData_Alloc(size_t size)
3593 // align to 16 byte boundary
3594 size = (size + 15) & ~15;
3595 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
3596 r_framedata_current += size;
3599 if (r_framedata_current > r_framedata_size)
3600 r_framedata_failed = true;
3602 // return NULL on everything after a failure
3603 if (r_framedata_failed)
3609 void *R_FrameData_Store(size_t size, void *data)
3611 void *d = R_FrameData_Alloc(size);
3613 memcpy(d, data, size);
3617 //==================================================================================
3619 // LordHavoc: animcache originally written by Echon, rewritten since then
3622 * Animation cache prevents re-generating mesh data for an animated model
3623 * multiple times in one frame for lighting, shadowing, reflections, etc.
3626 void R_AnimCache_Free(void)
3630 void R_AnimCache_ClearCache(void)
3633 entity_render_t *ent;
3635 for (i = 0;i < r_refdef.scene.numentities;i++)
3637 ent = r_refdef.scene.entities[i];
3638 ent->animcache_vertex3f = NULL;
3639 ent->animcache_normal3f = NULL;
3640 ent->animcache_svector3f = NULL;
3641 ent->animcache_tvector3f = NULL;
3645 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3647 dp_model_t *model = ent->model;
3649 // see if it's already cached this frame
3650 if (ent->animcache_vertex3f)
3652 // add normals/tangents if needed
3653 if (wantnormals || wanttangents)
3655 if (ent->animcache_normal3f)
3656 wantnormals = false;
3657 if (ent->animcache_svector3f)
3658 wanttangents = false;
3659 if (wantnormals || wanttangents)
3661 numvertices = model->surfmesh.num_vertices;
3663 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3666 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3667 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3669 if (!r_framedata_failed)
3670 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
3676 // see if this ent is worth caching
3677 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
3679 // get some memory for this entity and generate mesh data
3680 numvertices = model->surfmesh.num_vertices;
3681 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3683 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3686 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3687 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3689 if (!r_framedata_failed)
3690 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
3692 return !r_framedata_failed;
3695 void R_AnimCache_CacheVisibleEntities(void)
3698 qboolean wantnormals = !r_showsurfaces.integer;
3699 qboolean wanttangents = !r_showsurfaces.integer;
3701 switch(vid.renderpath)
3703 case RENDERPATH_GL20:
3705 case RENDERPATH_GL13:
3706 case RENDERPATH_GL11:
3707 wanttangents = false;
3711 // TODO: thread this
3712 // NOTE: R_PrepareRTLights() also caches entities
3714 for (i = 0;i < r_refdef.scene.numentities;i++)
3715 if (r_refdef.viewcache.entityvisible[i])
3716 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3718 if (r_shadows.integer)
3719 for (i = 0;i < r_refdef.scene.numentities;i++)
3720 if (!r_refdef.viewcache.entityvisible[i])
3721 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
3724 //==================================================================================
3726 static void R_View_UpdateEntityLighting (void)
3729 entity_render_t *ent;
3730 vec3_t tempdiffusenormal, avg;
3731 vec_t f, fa, fd, fdd;
3733 for (i = 0;i < r_refdef.scene.numentities;i++)
3735 ent = r_refdef.scene.entities[i];
3737 // skip unseen models
3738 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3742 if (ent->model && ent->model->brush.num_leafs)
3744 // TODO: use modellight for r_ambient settings on world?
3745 VectorSet(ent->modellight_ambient, 0, 0, 0);
3746 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3747 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3751 // fetch the lighting from the worldmodel data
3752 VectorClear(ent->modellight_ambient);
3753 VectorClear(ent->modellight_diffuse);
3754 VectorClear(tempdiffusenormal);
3755 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3758 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3759 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3760 if(ent->flags & RENDER_EQUALIZE)
3762 // first fix up ambient lighting...
3763 if(r_equalize_entities_minambient.value > 0)
3765 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3768 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3769 if(fa < r_equalize_entities_minambient.value * fd)
3772 // fa'/fd' = minambient
3773 // fa'+0.25*fd' = fa+0.25*fd
3775 // fa' = fd' * minambient
3776 // fd'*(0.25+minambient) = fa+0.25*fd
3778 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3779 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3781 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3782 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
3783 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3784 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3789 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3791 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3792 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3795 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3796 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3797 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3803 VectorSet(ent->modellight_ambient, 1, 1, 1);
3805 // move the light direction into modelspace coordinates for lighting code
3806 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3807 if(VectorLength2(ent->modellight_lightdir) == 0)
3808 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3809 VectorNormalize(ent->modellight_lightdir);
3813 #define MAX_LINEOFSIGHTTRACES 64
3815 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3818 vec3_t boxmins, boxmaxs;
3821 dp_model_t *model = r_refdef.scene.worldmodel;
3823 if (!model || !model->brush.TraceLineOfSight)
3826 // expand the box a little
3827 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3828 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3829 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3830 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3831 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3832 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3835 VectorCopy(eye, start);
3836 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3837 if (model->brush.TraceLineOfSight(model, start, end))
3840 // try various random positions
3841 for (i = 0;i < numsamples;i++)
3843 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3844 if (model->brush.TraceLineOfSight(model, start, end))
3852 static void R_View_UpdateEntityVisible (void)
3857 entity_render_t *ent;
3859 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3860 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3862 // worldmodel can check visibility
3863 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3864 for (i = 0;i < r_refdef.scene.numentities;i++)
3866 ent = r_refdef.scene.entities[i];
3867 if (!(ent->flags & renderimask))
3868 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)))
3869 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
3870 r_refdef.viewcache.entityvisible[i] = true;
3872 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3874 for (i = 0;i < r_refdef.scene.numentities;i++)
3876 ent = r_refdef.scene.entities[i];
3877 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3879 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3881 continue; // temp entities do pvs only
3882 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3883 ent->last_trace_visibility = realtime;
3884 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3885 r_refdef.viewcache.entityvisible[i] = 0;
3892 // no worldmodel or it can't check visibility
3893 for (i = 0;i < r_refdef.scene.numentities;i++)
3895 ent = r_refdef.scene.entities[i];
3896 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));
3901 /// only used if skyrendermasked, and normally returns false
3902 int R_DrawBrushModelsSky (void)
3905 entity_render_t *ent;
3908 for (i = 0;i < r_refdef.scene.numentities;i++)
3910 if (!r_refdef.viewcache.entityvisible[i])
3912 ent = r_refdef.scene.entities[i];
3913 if (!ent->model || !ent->model->DrawSky)
3915 ent->model->DrawSky(ent);
3921 static void R_DrawNoModel(entity_render_t *ent);
3922 static void R_DrawModels(void)
3925 entity_render_t *ent;
3927 for (i = 0;i < r_refdef.scene.numentities;i++)
3929 if (!r_refdef.viewcache.entityvisible[i])
3931 ent = r_refdef.scene.entities[i];
3932 r_refdef.stats.entities++;
3933 if (ent->model && ent->model->Draw != NULL)
3934 ent->model->Draw(ent);
3940 static void R_DrawModelsDepth(void)
3943 entity_render_t *ent;
3945 for (i = 0;i < r_refdef.scene.numentities;i++)
3947 if (!r_refdef.viewcache.entityvisible[i])
3949 ent = r_refdef.scene.entities[i];
3950 if (ent->model && ent->model->DrawDepth != NULL)
3951 ent->model->DrawDepth(ent);
3955 static void R_DrawModelsDebug(void)
3958 entity_render_t *ent;
3960 for (i = 0;i < r_refdef.scene.numentities;i++)
3962 if (!r_refdef.viewcache.entityvisible[i])
3964 ent = r_refdef.scene.entities[i];
3965 if (ent->model && ent->model->DrawDebug != NULL)
3966 ent->model->DrawDebug(ent);
3970 static void R_DrawModelsAddWaterPlanes(void)
3973 entity_render_t *ent;
3975 for (i = 0;i < r_refdef.scene.numentities;i++)
3977 if (!r_refdef.viewcache.entityvisible[i])
3979 ent = r_refdef.scene.entities[i];
3980 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3981 ent->model->DrawAddWaterPlanes(ent);
3985 static void R_View_SetFrustum(void)
3988 double slopex, slopey;
3989 vec3_t forward, left, up, origin;
3991 // we can't trust r_refdef.view.forward and friends in reflected scenes
3992 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3995 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3996 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3997 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3998 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3999 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4000 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4001 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4002 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4003 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4004 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4005 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4006 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4010 zNear = r_refdef.nearclip;
4011 nudge = 1.0 - 1.0 / (1<<23);
4012 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4013 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4014 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4015 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4016 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4017 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4018 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4019 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4025 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4026 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4027 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4028 r_refdef.view.frustum[0].dist = m[15] - m[12];
4030 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4031 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4032 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4033 r_refdef.view.frustum[1].dist = m[15] + m[12];
4035 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4036 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4037 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4038 r_refdef.view.frustum[2].dist = m[15] - m[13];
4040 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4041 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4042 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4043 r_refdef.view.frustum[3].dist = m[15] + m[13];
4045 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4046 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4047 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4048 r_refdef.view.frustum[4].dist = m[15] - m[14];
4050 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4051 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4052 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4053 r_refdef.view.frustum[5].dist = m[15] + m[14];
4056 if (r_refdef.view.useperspective)
4058 slopex = 1.0 / r_refdef.view.frustum_x;
4059 slopey = 1.0 / r_refdef.view.frustum_y;
4060 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4061 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
4062 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
4063 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
4064 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4066 // Leaving those out was a mistake, those were in the old code, and they
4067 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4068 // I couldn't reproduce it after adding those normalizations. --blub
4069 VectorNormalize(r_refdef.view.frustum[0].normal);
4070 VectorNormalize(r_refdef.view.frustum[1].normal);
4071 VectorNormalize(r_refdef.view.frustum[2].normal);
4072 VectorNormalize(r_refdef.view.frustum[3].normal);
4074 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4075 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]);
4076 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]);
4077 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]);
4078 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]);
4080 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4081 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4082 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4083 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4084 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4088 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4089 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4090 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4091 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4092 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4093 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4094 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4095 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4096 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4097 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4099 r_refdef.view.numfrustumplanes = 5;
4101 if (r_refdef.view.useclipplane)
4103 r_refdef.view.numfrustumplanes = 6;
4104 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4107 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4108 PlaneClassify(r_refdef.view.frustum + i);
4110 // LordHavoc: note to all quake engine coders, Quake had a special case
4111 // for 90 degrees which assumed a square view (wrong), so I removed it,
4112 // Quake2 has it disabled as well.
4114 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4115 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4116 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4117 //PlaneClassify(&frustum[0]);
4119 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4120 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4121 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4122 //PlaneClassify(&frustum[1]);
4124 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4125 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4126 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4127 //PlaneClassify(&frustum[2]);
4129 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4130 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4131 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4132 //PlaneClassify(&frustum[3]);
4135 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4136 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4137 //PlaneClassify(&frustum[4]);
4140 void R_View_Update(void)
4142 R_Main_ResizeViewCache();
4143 R_View_SetFrustum();
4144 R_View_WorldVisibility(r_refdef.view.useclipplane);
4145 R_View_UpdateEntityVisible();
4146 R_View_UpdateEntityLighting();
4149 void R_SetupView(qboolean allowwaterclippingplane)
4151 const double *customclipplane = NULL;
4153 if (r_refdef.view.useclipplane && allowwaterclippingplane)
4155 // LordHavoc: couldn't figure out how to make this approach the
4156 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4157 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4158 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4159 dist = r_refdef.view.clipplane.dist;
4160 plane[0] = r_refdef.view.clipplane.normal[0];
4161 plane[1] = r_refdef.view.clipplane.normal[1];
4162 plane[2] = r_refdef.view.clipplane.normal[2];
4164 customclipplane = plane;
4167 if (!r_refdef.view.useperspective)
4168 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);
4169 else if (vid.stencil && r_useinfinitefarclip.integer)
4170 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);
4172 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);
4173 R_SetViewport(&r_refdef.view.viewport);
4176 void R_ResetViewRendering2D(void)
4178 r_viewport_t viewport;
4181 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4182 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);
4183 R_SetViewport(&viewport);
4184 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
4185 GL_Color(1, 1, 1, 1);
4186 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4187 GL_BlendFunc(GL_ONE, GL_ZERO);
4188 GL_AlphaTest(false);
4189 GL_ScissorTest(false);
4190 GL_DepthMask(false);
4191 GL_DepthRange(0, 1);
4192 GL_DepthTest(false);
4193 R_Mesh_Matrix(&identitymatrix);
4194 R_Mesh_ResetTextureState();
4195 GL_PolygonOffset(0, 0);
4196 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4197 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4198 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4199 qglStencilMask(~0);CHECKGLERROR
4200 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4201 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4202 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
4203 R_SetupGenericShader(true);
4206 void R_ResetViewRendering3D(void)
4211 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4212 GL_Color(1, 1, 1, 1);
4213 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4214 GL_BlendFunc(GL_ONE, GL_ZERO);
4215 GL_AlphaTest(false);
4216 GL_ScissorTest(true);
4218 GL_DepthRange(0, 1);
4220 R_Mesh_Matrix(&identitymatrix);
4221 R_Mesh_ResetTextureState();
4222 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4223 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4224 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4225 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4226 qglStencilMask(~0);CHECKGLERROR
4227 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4228 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4229 GL_CullFace(r_refdef.view.cullface_back);
4230 R_SetupGenericShader(true);
4233 void R_RenderScene(void);
4234 void R_RenderWaterPlanes(void);
4236 static void R_Water_StartFrame(void)
4239 int waterwidth, waterheight, texturewidth, textureheight;
4240 r_waterstate_waterplane_t *p;
4242 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
4245 switch(vid.renderpath)
4247 case RENDERPATH_GL20:
4249 case RENDERPATH_GL13:
4250 case RENDERPATH_GL11:
4254 // set waterwidth and waterheight to the water resolution that will be
4255 // used (often less than the screen resolution for faster rendering)
4256 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4257 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4259 // calculate desired texture sizes
4260 // can't use water if the card does not support the texture size
4261 if (!r_water.integer || r_showsurfaces.integer)
4262 texturewidth = textureheight = waterwidth = waterheight = 0;
4263 else if (vid.support.arb_texture_non_power_of_two)
4265 texturewidth = waterwidth;
4266 textureheight = waterheight;
4270 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4271 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4274 // allocate textures as needed
4275 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4277 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4278 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4280 if (p->texture_refraction)
4281 R_FreeTexture(p->texture_refraction);
4282 p->texture_refraction = NULL;
4283 if (p->texture_reflection)
4284 R_FreeTexture(p->texture_reflection);
4285 p->texture_reflection = NULL;
4287 memset(&r_waterstate, 0, sizeof(r_waterstate));
4288 r_waterstate.texturewidth = texturewidth;
4289 r_waterstate.textureheight = textureheight;
4292 if (r_waterstate.texturewidth)
4294 r_waterstate.enabled = true;
4296 // when doing a reduced render (HDR) we want to use a smaller area
4297 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4298 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4300 // set up variables that will be used in shader setup
4301 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4302 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4303 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4304 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4307 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4308 r_waterstate.numwaterplanes = 0;
4311 void R_Water_AddWaterPlane(msurface_t *surface)
4313 int triangleindex, planeindex;
4319 r_waterstate_waterplane_t *p;
4320 texture_t *t = R_GetCurrentTexture(surface->texture);
4321 // just use the first triangle with a valid normal for any decisions
4322 VectorClear(normal);
4323 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4325 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4326 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4327 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4328 TriangleNormal(vert[0], vert[1], vert[2], normal);
4329 if (VectorLength2(normal) >= 0.001)
4333 VectorCopy(normal, plane.normal);
4334 VectorNormalize(plane.normal);
4335 plane.dist = DotProduct(vert[0], plane.normal);
4336 PlaneClassify(&plane);
4337 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4339 // skip backfaces (except if nocullface is set)
4340 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4342 VectorNegate(plane.normal, plane.normal);
4344 PlaneClassify(&plane);
4348 // find a matching plane if there is one
4349 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4350 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4352 if (planeindex >= r_waterstate.maxwaterplanes)
4353 return; // nothing we can do, out of planes
4355 // if this triangle does not fit any known plane rendered this frame, add one
4356 if (planeindex >= r_waterstate.numwaterplanes)
4358 // store the new plane
4359 r_waterstate.numwaterplanes++;
4361 // clear materialflags and pvs
4362 p->materialflags = 0;
4363 p->pvsvalid = false;
4365 // merge this surface's materialflags into the waterplane
4366 p->materialflags |= t->currentmaterialflags;
4367 // merge this surface's PVS into the waterplane
4368 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4369 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4370 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4372 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4377 static void R_Water_ProcessPlanes(void)
4379 r_refdef_view_t originalview;
4380 r_refdef_view_t myview;
4382 r_waterstate_waterplane_t *p;
4384 originalview = r_refdef.view;
4386 // make sure enough textures are allocated
4387 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4389 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4391 if (!p->texture_refraction)
4392 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);
4393 if (!p->texture_refraction)
4397 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4399 if (!p->texture_reflection)
4400 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);
4401 if (!p->texture_reflection)
4407 r_refdef.view = originalview;
4408 r_refdef.view.showdebug = false;
4409 r_refdef.view.width = r_waterstate.waterwidth;
4410 r_refdef.view.height = r_waterstate.waterheight;
4411 r_refdef.view.useclipplane = true;
4412 myview = r_refdef.view;
4413 r_waterstate.renderingscene = true;
4414 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4416 // render the normal view scene and copy into texture
4417 // (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)
4418 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4420 r_refdef.view = myview;
4421 r_refdef.view.clipplane = p->plane;
4422 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4423 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4424 PlaneClassify(&r_refdef.view.clipplane);
4426 R_ResetViewRendering3D();
4427 R_ClearScreen(r_refdef.fogenabled);
4431 // copy view into the screen texture
4432 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4433 GL_ActiveTexture(0);
4435 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
4438 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4440 r_refdef.view = myview;
4441 // render reflected scene and copy into texture
4442 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4443 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4444 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4445 r_refdef.view.clipplane = p->plane;
4446 // reverse the cullface settings for this render
4447 r_refdef.view.cullface_front = GL_FRONT;
4448 r_refdef.view.cullface_back = GL_BACK;
4449 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4451 r_refdef.view.usecustompvs = true;
4453 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4455 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4458 R_ResetViewRendering3D();
4459 R_ClearScreen(r_refdef.fogenabled);
4463 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4464 GL_ActiveTexture(0);
4466 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
4469 r_waterstate.renderingscene = false;
4470 r_refdef.view = originalview;
4471 R_ResetViewRendering3D();
4472 R_ClearScreen(r_refdef.fogenabled);
4476 r_refdef.view = originalview;
4477 r_waterstate.renderingscene = false;
4478 Cvar_SetValueQuick(&r_water, 0);
4479 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4483 void R_Bloom_StartFrame(void)
4485 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4487 switch(vid.renderpath)
4489 case RENDERPATH_GL20:
4491 case RENDERPATH_GL13:
4492 case RENDERPATH_GL11:
4496 // set bloomwidth and bloomheight to the bloom resolution that will be
4497 // used (often less than the screen resolution for faster rendering)
4498 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4499 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4500 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4501 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
4502 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
4504 // calculate desired texture sizes
4505 if (vid.support.arb_texture_non_power_of_two)
4507 screentexturewidth = r_refdef.view.width;
4508 screentextureheight = r_refdef.view.height;
4509 bloomtexturewidth = r_bloomstate.bloomwidth;
4510 bloomtextureheight = r_bloomstate.bloomheight;
4514 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4515 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4516 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4517 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4520 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 > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
4522 Cvar_SetValueQuick(&r_hdr, 0);
4523 Cvar_SetValueQuick(&r_bloom, 0);
4524 Cvar_SetValueQuick(&r_motionblur, 0);
4525 Cvar_SetValueQuick(&r_damageblur, 0);
4528 if (!(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)))
4529 screentexturewidth = screentextureheight = 0;
4530 if (!r_hdr.integer && !r_bloom.integer)
4531 bloomtexturewidth = bloomtextureheight = 0;
4533 // allocate textures as needed
4534 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4536 if (r_bloomstate.texture_screen)
4537 R_FreeTexture(r_bloomstate.texture_screen);
4538 r_bloomstate.texture_screen = NULL;
4539 r_bloomstate.screentexturewidth = screentexturewidth;
4540 r_bloomstate.screentextureheight = screentextureheight;
4541 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4542 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);
4544 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4546 if (r_bloomstate.texture_bloom)
4547 R_FreeTexture(r_bloomstate.texture_bloom);
4548 r_bloomstate.texture_bloom = NULL;
4549 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4550 r_bloomstate.bloomtextureheight = bloomtextureheight;
4551 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4552 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);
4555 // when doing a reduced render (HDR) we want to use a smaller area
4556 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4557 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4558 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4559 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4560 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4562 // set up a texcoord array for the full resolution screen image
4563 // (we have to keep this around to copy back during final render)
4564 r_bloomstate.screentexcoord2f[0] = 0;
4565 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4566 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4567 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4568 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4569 r_bloomstate.screentexcoord2f[5] = 0;
4570 r_bloomstate.screentexcoord2f[6] = 0;
4571 r_bloomstate.screentexcoord2f[7] = 0;
4573 // set up a texcoord array for the reduced resolution bloom image
4574 // (which will be additive blended over the screen image)
4575 r_bloomstate.bloomtexcoord2f[0] = 0;
4576 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4577 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4578 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4579 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4580 r_bloomstate.bloomtexcoord2f[5] = 0;
4581 r_bloomstate.bloomtexcoord2f[6] = 0;
4582 r_bloomstate.bloomtexcoord2f[7] = 0;
4584 if (r_hdr.integer || r_bloom.integer)
4586 r_bloomstate.enabled = true;
4587 r_bloomstate.hdr = r_hdr.integer != 0;
4590 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);
4593 void R_Bloom_CopyBloomTexture(float colorscale)
4595 r_refdef.stats.bloom++;
4597 // scale down screen texture to the bloom texture size
4599 R_SetViewport(&r_bloomstate.viewport);
4600 GL_BlendFunc(GL_ONE, GL_ZERO);
4601 GL_Color(colorscale, colorscale, colorscale, 1);
4602 // TODO: optimize with multitexture or GLSL
4603 R_SetupGenericShader(true);
4604 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4605 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4606 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4607 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4609 // we now have a bloom image in the framebuffer
4610 // copy it into the bloom image texture for later processing
4611 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4612 GL_ActiveTexture(0);
4614 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4615 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4618 void R_Bloom_CopyHDRTexture(void)
4620 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4621 GL_ActiveTexture(0);
4623 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
4624 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4627 void R_Bloom_MakeTexture(void)
4630 float xoffset, yoffset, r, brighten;
4632 r_refdef.stats.bloom++;
4634 R_ResetViewRendering2D();
4635 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4636 R_Mesh_ColorPointer(NULL, 0, 0);
4637 R_SetupGenericShader(true);
4639 // we have a bloom image in the framebuffer
4641 R_SetViewport(&r_bloomstate.viewport);
4643 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4646 r = bound(0, r_bloom_colorexponent.value / x, 1);
4647 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4648 GL_Color(r, r, r, 1);
4649 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4650 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4651 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4652 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4654 // copy the vertically blurred bloom view to a texture
4655 GL_ActiveTexture(0);
4657 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4658 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4661 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4662 brighten = r_bloom_brighten.value;
4664 brighten *= r_hdr_range.value;
4665 brighten = sqrt(brighten);
4667 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4668 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4669 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4671 for (dir = 0;dir < 2;dir++)
4673 // blend on at multiple vertical offsets to achieve a vertical blur
4674 // TODO: do offset blends using GLSL
4675 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4676 GL_BlendFunc(GL_ONE, GL_ZERO);
4677 for (x = -range;x <= range;x++)
4679 if (!dir){xoffset = 0;yoffset = x;}
4680 else {xoffset = x;yoffset = 0;}
4681 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4682 yoffset /= (float)r_bloomstate.bloomtextureheight;
4683 // compute a texcoord array with the specified x and y offset
4684 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4685 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4686 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4687 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4688 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4689 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4690 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4691 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4692 // this r value looks like a 'dot' particle, fading sharply to
4693 // black at the edges
4694 // (probably not realistic but looks good enough)
4695 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4696 //r = brighten/(range*2+1);
4697 r = brighten / (range * 2 + 1);
4699 r *= (1 - x*x/(float)(range*range));
4700 GL_Color(r, r, r, 1);
4701 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4702 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4703 GL_BlendFunc(GL_ONE, GL_ONE);
4706 // copy the vertically blurred bloom view to a texture
4707 GL_ActiveTexture(0);
4709 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4710 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4713 // apply subtract last
4714 // (just like it would be in a GLSL shader)
4715 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
4717 GL_BlendFunc(GL_ONE, GL_ZERO);
4718 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4719 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4720 GL_Color(1, 1, 1, 1);
4721 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4722 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4724 GL_BlendFunc(GL_ONE, GL_ONE);
4725 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4726 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4727 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4728 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4729 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4730 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4731 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4733 // copy the darkened bloom view to a texture
4734 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4735 GL_ActiveTexture(0);
4737 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4738 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4742 void R_HDR_RenderBloomTexture(void)
4744 int oldwidth, oldheight;
4745 float oldcolorscale;
4747 oldcolorscale = r_refdef.view.colorscale;
4748 oldwidth = r_refdef.view.width;
4749 oldheight = r_refdef.view.height;
4750 r_refdef.view.width = r_bloomstate.bloomwidth;
4751 r_refdef.view.height = r_bloomstate.bloomheight;
4753 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4754 // TODO: add exposure compensation features
4755 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4757 r_refdef.view.showdebug = false;
4758 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4760 R_ResetViewRendering3D();
4762 R_ClearScreen(r_refdef.fogenabled);
4763 if (r_timereport_active)
4764 R_TimeReport("HDRclear");
4767 if (r_timereport_active)
4768 R_TimeReport("visibility");
4770 // only do secondary renders with HDR if r_hdr is 2 or higher
4771 r_waterstate.numwaterplanes = 0;
4772 if (r_waterstate.enabled && r_hdr.integer >= 2)
4773 R_RenderWaterPlanes();
4775 r_refdef.view.showdebug = true;
4777 r_waterstate.numwaterplanes = 0;
4779 R_ResetViewRendering2D();
4781 R_Bloom_CopyHDRTexture();
4782 R_Bloom_MakeTexture();
4784 // restore the view settings
4785 r_refdef.view.width = oldwidth;
4786 r_refdef.view.height = oldheight;
4787 r_refdef.view.colorscale = oldcolorscale;
4789 R_ResetViewRendering3D();
4791 R_ClearScreen(r_refdef.fogenabled);
4792 if (r_timereport_active)
4793 R_TimeReport("viewclear");
4796 static void R_BlendView(void)
4798 unsigned int permutation;
4800 switch (vid.renderpath)
4802 case RENDERPATH_GL20:
4804 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4805 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4806 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4807 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4808 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4810 if (r_bloomstate.texture_screen)
4812 // make sure the buffer is available
4813 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4815 R_ResetViewRendering2D();
4816 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4817 R_Mesh_ColorPointer(NULL, 0, 0);
4818 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4819 GL_ActiveTexture(0);CHECKGLERROR
4821 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4823 // declare variables
4825 static float avgspeed;
4827 speed = VectorLength(cl.movement_velocity);
4829 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4830 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4832 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4833 speed = bound(0, speed, 1);
4834 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4836 // calculate values into a standard alpha
4837 cl.motionbluralpha = 1 - exp(-
4839 (r_motionblur.value * speed / 80)
4841 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4844 max(0.0001, cl.time - cl.oldtime) // fps independent
4847 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4848 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4850 if (cl.motionbluralpha > 0)
4852 R_SetupGenericShader(true);
4853 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4854 GL_Color(1, 1, 1, cl.motionbluralpha);
4855 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4856 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4857 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4858 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4862 // copy view into the screen texture
4863 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
4864 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4866 else if (!r_bloomstate.texture_bloom)
4868 // we may still have to do view tint...
4869 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4871 // apply a color tint to the whole view
4872 R_ResetViewRendering2D();
4873 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4874 R_Mesh_ColorPointer(NULL, 0, 0);
4875 R_SetupGenericShader(false);
4876 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4877 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4878 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4880 break; // no screen processing, no bloom, skip it
4883 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4885 // render simple bloom effect
4886 // copy the screen and shrink it and darken it for the bloom process
4887 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4888 // make the bloom texture
4889 R_Bloom_MakeTexture();
4892 R_ResetViewRendering2D();
4893 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4894 R_Mesh_ColorPointer(NULL, 0, 0);
4895 GL_Color(1, 1, 1, 1);
4896 GL_BlendFunc(GL_ONE, GL_ZERO);
4897 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4898 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4899 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4900 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4901 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4902 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4903 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4904 if (r_glsl_permutation->loc_ViewTintColor >= 0)
4905 qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4906 if (r_glsl_permutation->loc_ClientTime >= 0)
4907 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4908 if (r_glsl_permutation->loc_PixelSize >= 0)
4909 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4910 if (r_glsl_permutation->loc_UserVec1 >= 0)
4912 float a=0, b=0, c=0, d=0;
4913 #if _MSC_VER >= 1400
4914 #define sscanf sscanf_s
4916 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4917 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4919 if (r_glsl_permutation->loc_UserVec2 >= 0)
4921 float a=0, b=0, c=0, d=0;
4922 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4923 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4925 if (r_glsl_permutation->loc_UserVec3 >= 0)
4927 float a=0, b=0, c=0, d=0;
4928 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4929 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4931 if (r_glsl_permutation->loc_UserVec4 >= 0)
4933 float a=0, b=0, c=0, d=0;
4934 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4935 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4937 if (r_glsl_permutation->loc_Saturation >= 0)
4938 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4939 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4940 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4942 case RENDERPATH_GL13:
4943 case RENDERPATH_GL11:
4944 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4946 // apply a color tint to the whole view
4947 R_ResetViewRendering2D();
4948 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4949 R_Mesh_ColorPointer(NULL, 0, 0);
4950 R_SetupGenericShader(false);
4951 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4952 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4953 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4959 matrix4x4_t r_waterscrollmatrix;
4961 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4963 if (r_refdef.fog_density)
4965 r_refdef.fogcolor[0] = r_refdef.fog_red;
4966 r_refdef.fogcolor[1] = r_refdef.fog_green;
4967 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4969 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4970 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4971 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4972 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4976 VectorCopy(r_refdef.fogcolor, fogvec);
4977 // color.rgb *= ContrastBoost * SceneBrightness;
4978 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4979 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4980 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4981 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4986 void R_UpdateVariables(void)
4990 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
4992 r_refdef.farclip = r_farclip_base.value;
4993 if (r_refdef.scene.worldmodel)
4994 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4995 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4997 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4998 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4999 r_refdef.polygonfactor = 0;
5000 r_refdef.polygonoffset = 0;
5001 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5002 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5004 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5005 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5006 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5007 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5008 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5009 if (r_showsurfaces.integer)
5011 r_refdef.scene.rtworld = false;
5012 r_refdef.scene.rtworldshadows = false;
5013 r_refdef.scene.rtdlight = false;
5014 r_refdef.scene.rtdlightshadows = false;
5015 r_refdef.lightmapintensity = 0;
5018 if (gamemode == GAME_NEHAHRA)
5020 if (gl_fogenable.integer)
5022 r_refdef.oldgl_fogenable = true;
5023 r_refdef.fog_density = gl_fogdensity.value;
5024 r_refdef.fog_red = gl_fogred.value;
5025 r_refdef.fog_green = gl_foggreen.value;
5026 r_refdef.fog_blue = gl_fogblue.value;
5027 r_refdef.fog_alpha = 1;
5028 r_refdef.fog_start = 0;
5029 r_refdef.fog_end = gl_skyclip.value;
5030 r_refdef.fog_height = 1<<30;
5031 r_refdef.fog_fadedepth = 128;
5033 else if (r_refdef.oldgl_fogenable)
5035 r_refdef.oldgl_fogenable = false;
5036 r_refdef.fog_density = 0;
5037 r_refdef.fog_red = 0;
5038 r_refdef.fog_green = 0;
5039 r_refdef.fog_blue = 0;
5040 r_refdef.fog_alpha = 0;
5041 r_refdef.fog_start = 0;
5042 r_refdef.fog_end = 0;
5043 r_refdef.fog_height = 1<<30;
5044 r_refdef.fog_fadedepth = 128;
5048 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5049 r_refdef.fog_start = max(0, r_refdef.fog_start);
5050 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5052 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5054 if (r_refdef.fog_density && r_drawfog.integer)
5056 r_refdef.fogenabled = true;
5057 // this is the point where the fog reaches 0.9986 alpha, which we
5058 // consider a good enough cutoff point for the texture
5059 // (0.9986 * 256 == 255.6)
5060 if (r_fog_exp2.integer)
5061 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5063 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5064 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5065 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5066 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5067 // fog color was already set
5068 // update the fog texture
5069 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)
5070 R_BuildFogTexture();
5073 r_refdef.fogenabled = false;
5075 switch(vid.renderpath)
5077 case RENDERPATH_GL20:
5078 if(v_glslgamma.integer && !vid_gammatables_trivial)
5080 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5082 // build GLSL gamma texture
5083 #define RAMPWIDTH 256
5084 unsigned short ramp[RAMPWIDTH * 3];
5085 unsigned char rampbgr[RAMPWIDTH][4];
5088 r_texture_gammaramps_serial = vid_gammatables_serial;
5090 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5091 for(i = 0; i < RAMPWIDTH; ++i)
5093 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5094 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5095 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5098 if (r_texture_gammaramps)
5100 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5104 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);
5110 // remove GLSL gamma texture
5113 case RENDERPATH_GL13:
5114 case RENDERPATH_GL11:
5119 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5120 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5126 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5127 if( scenetype != r_currentscenetype ) {
5128 // store the old scenetype
5129 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5130 r_currentscenetype = scenetype;
5131 // move in the new scene
5132 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5141 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5143 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5144 if( scenetype == r_currentscenetype ) {
5145 return &r_refdef.scene;
5147 return &r_scenes_store[ scenetype ];
5156 void R_RenderView(void)
5158 if (r_timereport_active)
5159 R_TimeReport("start");
5160 r_frame++; // used only by R_GetCurrentTexture
5161 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5163 if (!r_drawentities.integer)
5164 r_refdef.scene.numentities = 0;
5166 R_AnimCache_ClearCache();
5167 R_FrameData_NewFrame();
5169 if (r_refdef.view.isoverlay)
5171 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5172 GL_Clear( GL_DEPTH_BUFFER_BIT );
5173 R_TimeReport("depthclear");
5175 r_refdef.view.showdebug = false;
5177 r_waterstate.enabled = false;
5178 r_waterstate.numwaterplanes = 0;
5186 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
5187 return; //Host_Error ("R_RenderView: NULL worldmodel");
5189 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
5191 // break apart the view matrix into vectors for various purposes
5192 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5193 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5194 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5195 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5196 // make an inverted copy of the view matrix for tracking sprites
5197 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5199 R_Shadow_UpdateWorldLightSelection();
5201 R_Bloom_StartFrame();
5202 R_Water_StartFrame();
5205 if (r_timereport_active)
5206 R_TimeReport("viewsetup");
5208 R_ResetViewRendering3D();
5210 if (r_refdef.view.clear || r_refdef.fogenabled)
5212 R_ClearScreen(r_refdef.fogenabled);
5213 if (r_timereport_active)
5214 R_TimeReport("viewclear");
5216 r_refdef.view.clear = true;
5218 // this produces a bloom texture to be used in R_BlendView() later
5219 if (r_hdr.integer && r_bloomstate.bloomwidth)
5220 R_HDR_RenderBloomTexture();
5222 r_refdef.view.showdebug = true;
5225 if (r_timereport_active)
5226 R_TimeReport("visibility");
5228 r_waterstate.numwaterplanes = 0;
5229 if (r_waterstate.enabled)
5230 R_RenderWaterPlanes();
5233 r_waterstate.numwaterplanes = 0;
5236 if (r_timereport_active)
5237 R_TimeReport("blendview");
5239 GL_Scissor(0, 0, vid.width, vid.height);
5240 GL_ScissorTest(false);
5244 void R_RenderWaterPlanes(void)
5246 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5248 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5249 if (r_timereport_active)
5250 R_TimeReport("waterworld");
5253 // don't let sound skip if going slow
5254 if (r_refdef.scene.extraupdate)
5257 R_DrawModelsAddWaterPlanes();
5258 if (r_timereport_active)
5259 R_TimeReport("watermodels");
5261 if (r_waterstate.numwaterplanes)
5263 R_Water_ProcessPlanes();
5264 if (r_timereport_active)
5265 R_TimeReport("waterscenes");
5269 extern void R_DrawLightningBeams (void);
5270 extern void VM_CL_AddPolygonsToMeshQueue (void);
5271 extern void R_DrawPortals (void);
5272 extern cvar_t cl_locs_show;
5273 static void R_DrawLocs(void);
5274 static void R_DrawEntityBBoxes(void);
5275 static void R_DrawModelDecals(void);
5276 extern cvar_t cl_decals_newsystem;
5277 extern qboolean r_shadow_usingdeferredprepass;
5278 void R_RenderScene(void)
5280 r_refdef.stats.renders++;
5284 // don't let sound skip if going slow
5285 if (r_refdef.scene.extraupdate)
5288 R_MeshQueue_BeginScene();
5292 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);
5294 if (cl.csqc_vidvars.drawworld)
5296 // don't let sound skip if going slow
5297 if (r_refdef.scene.extraupdate)
5300 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5302 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5303 if (r_timereport_active)
5304 R_TimeReport("worldsky");
5307 if (R_DrawBrushModelsSky() && r_timereport_active)
5308 R_TimeReport("bmodelsky");
5310 if (skyrendermasked && skyrenderlater)
5312 // we have to force off the water clipping plane while rendering sky
5316 if (r_timereport_active)
5317 R_TimeReport("sky");
5321 R_AnimCache_CacheVisibleEntities();
5322 if (r_timereport_active)
5323 R_TimeReport("animation");
5325 R_Shadow_PrepareLights();
5326 if (r_timereport_active)
5327 R_TimeReport("preparelights");
5329 if (r_shadow_usingdeferredprepass)
5330 R_Shadow_DrawPrepass();
5332 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5334 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5335 if (r_timereport_active)
5336 R_TimeReport("worlddepth");
5338 if (r_depthfirst.integer >= 2)
5340 R_DrawModelsDepth();
5341 if (r_timereport_active)
5342 R_TimeReport("modeldepth");
5345 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5347 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5348 if (r_timereport_active)
5349 R_TimeReport("world");
5352 // don't let sound skip if going slow
5353 if (r_refdef.scene.extraupdate)
5357 if (r_timereport_active)
5358 R_TimeReport("models");
5360 // don't let sound skip if going slow
5361 if (r_refdef.scene.extraupdate)
5364 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5366 R_DrawModelShadows();
5367 R_ResetViewRendering3D();
5368 // don't let sound skip if going slow
5369 if (r_refdef.scene.extraupdate)
5373 if (!r_shadow_usingdeferredprepass)
5375 R_Shadow_DrawLights();
5376 if (r_timereport_active)
5377 R_TimeReport("rtlights");
5380 // don't let sound skip if going slow
5381 if (r_refdef.scene.extraupdate)
5384 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5386 R_DrawModelShadows();
5387 R_ResetViewRendering3D();
5388 // don't let sound skip if going slow
5389 if (r_refdef.scene.extraupdate)
5393 if (cl.csqc_vidvars.drawworld)
5395 if (cl_decals_newsystem.integer)
5397 R_DrawModelDecals();
5398 if (r_timereport_active)
5399 R_TimeReport("modeldecals");
5404 if (r_timereport_active)
5405 R_TimeReport("decals");
5409 if (r_timereport_active)
5410 R_TimeReport("particles");
5413 if (r_timereport_active)
5414 R_TimeReport("explosions");
5416 R_DrawLightningBeams();
5417 if (r_timereport_active)
5418 R_TimeReport("lightning");
5421 R_SetupGenericShader(true);
5422 VM_CL_AddPolygonsToMeshQueue();
5424 if (r_refdef.view.showdebug)
5426 if (cl_locs_show.integer)
5429 if (r_timereport_active)
5430 R_TimeReport("showlocs");
5433 if (r_drawportals.integer)
5436 if (r_timereport_active)
5437 R_TimeReport("portals");
5440 if (r_showbboxes.value > 0)
5442 R_DrawEntityBBoxes();
5443 if (r_timereport_active)
5444 R_TimeReport("bboxes");
5448 R_SetupGenericShader(true);
5449 R_MeshQueue_RenderTransparent();
5450 if (r_timereport_active)
5451 R_TimeReport("drawtrans");
5453 R_SetupGenericShader(true);
5455 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))
5457 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5458 if (r_timereport_active)
5459 R_TimeReport("worlddebug");
5460 R_DrawModelsDebug();
5461 if (r_timereport_active)
5462 R_TimeReport("modeldebug");
5465 R_SetupGenericShader(true);
5467 if (cl.csqc_vidvars.drawworld)
5469 R_Shadow_DrawCoronas();
5470 if (r_timereport_active)
5471 R_TimeReport("coronas");
5474 // don't let sound skip if going slow
5475 if (r_refdef.scene.extraupdate)
5478 R_ResetViewRendering2D();
5481 static const unsigned short bboxelements[36] =
5491 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5494 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5496 RSurf_ActiveWorldEntity();
5498 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5499 GL_DepthMask(false);
5500 GL_DepthRange(0, 1);
5501 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5502 R_Mesh_ResetTextureState();
5504 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5505 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5506 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5507 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5508 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5509 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5510 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5511 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5512 R_FillColors(color4f, 8, cr, cg, cb, ca);
5513 if (r_refdef.fogenabled)
5515 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5517 f1 = RSurf_FogVertex(v);
5519 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5520 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5521 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5524 R_Mesh_VertexPointer(vertex3f, 0, 0);
5525 R_Mesh_ColorPointer(color4f, 0, 0);
5526 R_Mesh_ResetTextureState();
5527 R_SetupGenericShader(false);
5528 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5531 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5535 prvm_edict_t *edict;
5536 prvm_prog_t *prog_save = prog;
5538 // this function draws bounding boxes of server entities
5542 GL_CullFace(GL_NONE);
5543 R_SetupGenericShader(false);
5547 for (i = 0;i < numsurfaces;i++)
5549 edict = PRVM_EDICT_NUM(surfacelist[i]);
5550 switch ((int)edict->fields.server->solid)
5552 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5553 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5554 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5555 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5556 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5557 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5559 color[3] *= r_showbboxes.value;
5560 color[3] = bound(0, color[3], 1);
5561 GL_DepthTest(!r_showdisabledepthtest.integer);
5562 GL_CullFace(r_refdef.view.cullface_front);
5563 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5569 static void R_DrawEntityBBoxes(void)
5572 prvm_edict_t *edict;
5574 prvm_prog_t *prog_save = prog;
5576 // this function draws bounding boxes of server entities
5582 for (i = 0;i < prog->num_edicts;i++)
5584 edict = PRVM_EDICT_NUM(i);
5585 if (edict->priv.server->free)
5587 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5588 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5590 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5592 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5593 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5599 static const int nomodelelement3i[24] =
5611 static const unsigned short nomodelelement3s[24] =
5623 static const float nomodelvertex3f[6*3] =
5633 static const float nomodelcolor4f[6*4] =
5635 0.0f, 0.0f, 0.5f, 1.0f,
5636 0.0f, 0.0f, 0.5f, 1.0f,
5637 0.0f, 0.5f, 0.0f, 1.0f,
5638 0.0f, 0.5f, 0.0f, 1.0f,
5639 0.5f, 0.0f, 0.0f, 1.0f,
5640 0.5f, 0.0f, 0.0f, 1.0f
5643 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5649 RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
5651 // this is only called once per entity so numsurfaces is always 1, and
5652 // surfacelist is always {0}, so this code does not handle batches
5654 if (rsurface.ent_flags & RENDER_ADDITIVE)
5656 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5657 GL_DepthMask(false);
5659 else if (rsurface.colormod[3] < 1)
5661 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5662 GL_DepthMask(false);
5666 GL_BlendFunc(GL_ONE, GL_ZERO);
5669 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5670 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5671 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5672 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5673 R_SetupGenericShader(false);
5674 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5675 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5676 R_Mesh_ColorPointer(color4f, 0, 0);
5677 for (i = 0, c = color4f;i < 6;i++, c += 4)
5679 c[0] *= rsurface.colormod[0];
5680 c[1] *= rsurface.colormod[1];
5681 c[2] *= rsurface.colormod[2];
5682 c[3] *= rsurface.colormod[3];
5684 if (r_refdef.fogenabled)
5686 for (i = 0, c = color4f;i < 6;i++, c += 4)
5688 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5690 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5691 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5692 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5695 R_Mesh_ResetTextureState();
5696 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5699 void R_DrawNoModel(entity_render_t *ent)
5702 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5703 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5704 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5706 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5709 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5711 vec3_t right1, right2, diff, normal;
5713 VectorSubtract (org2, org1, normal);
5715 // calculate 'right' vector for start
5716 VectorSubtract (r_refdef.view.origin, org1, diff);
5717 CrossProduct (normal, diff, right1);
5718 VectorNormalize (right1);
5720 // calculate 'right' vector for end
5721 VectorSubtract (r_refdef.view.origin, org2, diff);
5722 CrossProduct (normal, diff, right2);
5723 VectorNormalize (right2);
5725 vert[ 0] = org1[0] + width * right1[0];
5726 vert[ 1] = org1[1] + width * right1[1];
5727 vert[ 2] = org1[2] + width * right1[2];
5728 vert[ 3] = org1[0] - width * right1[0];
5729 vert[ 4] = org1[1] - width * right1[1];
5730 vert[ 5] = org1[2] - width * right1[2];
5731 vert[ 6] = org2[0] - width * right2[0];
5732 vert[ 7] = org2[1] - width * right2[1];
5733 vert[ 8] = org2[2] - width * right2[2];
5734 vert[ 9] = org2[0] + width * right2[0];
5735 vert[10] = org2[1] + width * right2[1];
5736 vert[11] = org2[2] + width * right2[2];
5739 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
5741 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5742 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5743 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5744 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5745 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5746 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5747 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5748 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5749 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5750 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5751 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5752 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5755 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5760 VectorSet(v, x, y, z);
5761 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5762 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5764 if (i == mesh->numvertices)
5766 if (mesh->numvertices < mesh->maxvertices)
5768 VectorCopy(v, vertex3f);
5769 mesh->numvertices++;
5771 return mesh->numvertices;
5777 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5781 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5782 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5783 e = mesh->element3i + mesh->numtriangles * 3;
5784 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5786 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5787 if (mesh->numtriangles < mesh->maxtriangles)
5792 mesh->numtriangles++;
5794 element[1] = element[2];
5798 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5802 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5803 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5804 e = mesh->element3i + mesh->numtriangles * 3;
5805 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5807 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5808 if (mesh->numtriangles < mesh->maxtriangles)
5813 mesh->numtriangles++;
5815 element[1] = element[2];
5819 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5820 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5822 int planenum, planenum2;
5825 mplane_t *plane, *plane2;
5827 double temppoints[2][256*3];
5828 // figure out how large a bounding box we need to properly compute this brush
5830 for (w = 0;w < numplanes;w++)
5831 maxdist = max(maxdist, fabs(planes[w].dist));
5832 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5833 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5834 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5838 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5839 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5841 if (planenum2 == planenum)
5843 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);
5846 if (tempnumpoints < 3)
5848 // generate elements forming a triangle fan for this polygon
5849 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5853 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)
5855 texturelayer_t *layer;
5856 layer = t->currentlayers + t->currentnumlayers++;
5858 layer->depthmask = depthmask;
5859 layer->blendfunc1 = blendfunc1;
5860 layer->blendfunc2 = blendfunc2;
5861 layer->texture = texture;
5862 layer->texmatrix = *matrix;
5863 layer->color[0] = r;
5864 layer->color[1] = g;
5865 layer->color[2] = b;
5866 layer->color[3] = a;
5869 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5872 index = parms[2] + r_refdef.scene.time * parms[3];
5873 index -= floor(index);
5877 case Q3WAVEFUNC_NONE:
5878 case Q3WAVEFUNC_NOISE:
5879 case Q3WAVEFUNC_COUNT:
5882 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5883 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5884 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5885 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5886 case Q3WAVEFUNC_TRIANGLE:
5888 f = index - floor(index);
5899 return (float)(parms[0] + parms[1] * f);
5902 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5907 matrix4x4_t matrix, temp;
5908 switch(tcmod->tcmod)
5912 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5913 matrix = r_waterscrollmatrix;
5915 matrix = identitymatrix;
5917 case Q3TCMOD_ENTITYTRANSLATE:
5918 // this is used in Q3 to allow the gamecode to control texcoord
5919 // scrolling on the entity, which is not supported in darkplaces yet.
5920 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5922 case Q3TCMOD_ROTATE:
5923 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5924 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5925 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5928 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5930 case Q3TCMOD_SCROLL:
5931 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5933 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5934 w = (int) tcmod->parms[0];
5935 h = (int) tcmod->parms[1];
5936 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5938 idx = (int) floor(f * w * h);
5939 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5941 case Q3TCMOD_STRETCH:
5942 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5943 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5945 case Q3TCMOD_TRANSFORM:
5946 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5947 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5948 VectorSet(tcmat + 6, 0 , 0 , 1);
5949 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5950 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5952 case Q3TCMOD_TURBULENT:
5953 // this is handled in the RSurf_PrepareVertices function
5954 matrix = identitymatrix;
5958 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5961 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5963 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5964 char name[MAX_QPATH];
5965 skinframe_t *skinframe;
5966 unsigned char pixels[296*194];
5967 strlcpy(cache->name, skinname, sizeof(cache->name));
5968 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5969 if (developer_loading.integer)
5970 Con_Printf("loading %s\n", name);
5971 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5972 if (!skinframe || !skinframe->base)
5975 fs_offset_t filesize;
5977 f = FS_LoadFile(name, tempmempool, true, &filesize);
5980 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5981 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5985 cache->skinframe = skinframe;
5988 texture_t *R_GetCurrentTexture(texture_t *t)
5991 const entity_render_t *ent = rsurface.entity;
5992 dp_model_t *model = ent->model;
5993 q3shaderinfo_layer_tcmod_t *tcmod;
5995 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5996 return t->currentframe;
5997 t->update_lastrenderframe = r_frame;
5998 t->update_lastrenderentity = (void *)ent;
6000 // switch to an alternate material if this is a q1bsp animated material
6002 texture_t *texture = t;
6003 int s = rsurface.ent_skinnum;
6004 if ((unsigned int)s >= (unsigned int)model->numskins)
6006 if (model->skinscenes)
6008 if (model->skinscenes[s].framecount > 1)
6009 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6011 s = model->skinscenes[s].firstframe;
6014 t = t + s * model->num_surfaces;
6017 // use an alternate animation if the entity's frame is not 0,
6018 // and only if the texture has an alternate animation
6019 if (rsurface.ent_alttextures && t->anim_total[1])
6020 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6022 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6024 texture->currentframe = t;
6027 // update currentskinframe to be a qw skin or animation frame
6028 if (rsurface.ent_qwskin >= 0)
6030 i = rsurface.ent_qwskin;
6031 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6033 r_qwskincache_size = cl.maxclients;
6035 Mem_Free(r_qwskincache);
6036 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6038 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6039 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6040 t->currentskinframe = r_qwskincache[i].skinframe;
6041 if (t->currentskinframe == NULL)
6042 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6044 else if (t->numskinframes >= 2)
6045 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6046 if (t->backgroundnumskinframes >= 2)
6047 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6049 t->currentmaterialflags = t->basematerialflags;
6050 t->currentalpha = rsurface.colormod[3];
6051 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6052 t->currentalpha *= r_wateralpha.value;
6053 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6054 t->currentalpha *= t->r_water_wateralpha;
6055 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6056 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6057 if (!(rsurface.ent_flags & RENDER_LIGHT))
6058 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6059 else if (rsurface.modeltexcoordlightmap2f == NULL)
6061 // pick a model lighting mode
6062 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6063 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6065 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6067 if (rsurface.ent_flags & RENDER_ADDITIVE)
6068 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6069 else if (t->currentalpha < 1)
6070 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6071 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6072 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6073 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6074 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6075 if (t->backgroundnumskinframes)
6076 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6077 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6079 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6080 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6083 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6084 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6085 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6087 // there is no tcmod
6088 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6090 t->currenttexmatrix = r_waterscrollmatrix;
6091 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6093 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6095 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6096 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6099 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6100 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6101 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6102 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6104 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6105 if (t->currentskinframe->qpixels)
6106 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6107 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6108 t->glosstexture = r_texture_black;
6109 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6110 t->backgroundglosstexture = r_texture_black;
6111 t->specularpower = r_shadow_glossexponent.value;
6112 // TODO: store reference values for these in the texture?
6113 t->specularscale = 0;
6114 if (r_shadow_gloss.integer > 0)
6116 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6118 if (r_shadow_glossintensity.value > 0)
6120 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6121 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6122 t->specularscale = r_shadow_glossintensity.value;
6125 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6127 t->glosstexture = r_texture_white;
6128 t->backgroundglosstexture = r_texture_white;
6129 t->specularscale = r_shadow_gloss2intensity.value;
6130 t->specularpower = r_shadow_gloss2exponent.value;
6133 t->specularscale *= t->specularscalemod;
6134 t->specularpower *= t->specularpowermod;
6136 // lightmaps mode looks bad with dlights using actual texturing, so turn
6137 // off the colormap and glossmap, but leave the normalmap on as it still
6138 // accurately represents the shading involved
6139 if (gl_lightmaps.integer)
6141 t->basetexture = r_texture_grey128;
6142 t->backgroundbasetexture = NULL;
6143 t->specularscale = 0;
6144 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6147 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
6148 VectorClear(t->dlightcolor);
6149 t->currentnumlayers = 0;
6150 if (t->currentmaterialflags & MATERIALFLAG_WALL)
6153 int blendfunc1, blendfunc2;
6155 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6157 blendfunc1 = GL_SRC_ALPHA;
6158 blendfunc2 = GL_ONE;
6160 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6162 blendfunc1 = GL_SRC_ALPHA;
6163 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6165 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6167 blendfunc1 = t->customblendfunc[0];
6168 blendfunc2 = t->customblendfunc[1];
6172 blendfunc1 = GL_ONE;
6173 blendfunc2 = GL_ZERO;
6175 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
6176 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
6177 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
6178 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6180 // fullbright is not affected by r_refdef.lightmapintensity
6181 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]);
6182 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6183 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
6184 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6185 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
6189 vec3_t ambientcolor;
6191 // set the color tint used for lights affecting this surface
6192 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
6194 // q3bsp has no lightmap updates, so the lightstylevalue that
6195 // would normally be baked into the lightmap must be
6196 // applied to the color
6197 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
6198 if (model->type == mod_brushq3)
6199 colorscale *= r_refdef.scene.rtlightstylevalue[0];
6200 colorscale *= r_refdef.lightmapintensity;
6201 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
6202 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
6203 // basic lit geometry
6204 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]);
6205 // add pants/shirt if needed
6206 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6207 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
6208 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6209 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
6210 // now add ambient passes if needed
6211 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
6213 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]);
6214 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6215 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
6216 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6217 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
6220 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
6221 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
6222 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
6224 // if this is opaque use alpha blend which will darken the earlier
6227 // if this is an alpha blended material, all the earlier passes
6228 // were darkened by fog already, so we only need to add the fog
6229 // color ontop through the fog mask texture
6231 // if this is an additive blended material, all the earlier passes
6232 // were darkened by fog already, and we should not add fog color
6233 // (because the background was not darkened, there is no fog color
6234 // that was lost behind it).
6235 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &t->currenttexmatrix, 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]);
6239 return t->currentframe;
6242 rsurfacestate_t rsurface;
6244 void R_Mesh_ResizeArrays(int newvertices)
6247 if (rsurface.array_size >= newvertices)
6249 if (rsurface.array_modelvertex3f)
6250 Mem_Free(rsurface.array_modelvertex3f);
6251 rsurface.array_size = (newvertices + 1023) & ~1023;
6252 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6253 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
6254 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
6255 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
6256 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
6257 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
6258 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6259 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6260 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
6261 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
6262 rsurface.array_color4f = base + rsurface.array_size * 27;
6263 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6266 void RSurf_ActiveWorldEntity(void)
6268 dp_model_t *model = r_refdef.scene.worldmodel;
6269 //if (rsurface.entity == r_refdef.scene.worldentity)
6271 rsurface.entity = r_refdef.scene.worldentity;
6272 rsurface.skeleton = NULL;
6273 rsurface.ent_skinnum = 0;
6274 rsurface.ent_qwskin = -1;
6275 rsurface.ent_shadertime = 0;
6276 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6277 if (rsurface.array_size < model->surfmesh.num_vertices)
6278 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6279 rsurface.matrix = identitymatrix;
6280 rsurface.inversematrix = identitymatrix;
6281 rsurface.matrixscale = 1;
6282 rsurface.inversematrixscale = 1;
6283 R_Mesh_Matrix(&identitymatrix);
6284 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6285 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6286 rsurface.fograngerecip = r_refdef.fograngerecip;
6287 rsurface.fogheightfade = r_refdef.fogheightfade;
6288 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6289 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6290 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6291 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6292 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6293 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6294 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6295 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
6296 rsurface.colormod[3] = 1;
6297 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
6298 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6299 rsurface.frameblend[0].lerp = 1;
6300 rsurface.ent_alttextures = false;
6301 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6302 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6303 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6304 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6305 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6306 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6307 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6308 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6309 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6310 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6311 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6312 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6313 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6314 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6315 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6316 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6317 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6318 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6319 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6320 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6321 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6322 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6323 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6324 rsurface.modelelement3i = model->surfmesh.data_element3i;
6325 rsurface.modelelement3s = model->surfmesh.data_element3s;
6326 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6327 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6328 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6329 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6330 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6331 rsurface.modelsurfaces = model->data_surfaces;
6332 rsurface.generatedvertex = false;
6333 rsurface.vertex3f = rsurface.modelvertex3f;
6334 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6335 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6336 rsurface.svector3f = rsurface.modelsvector3f;
6337 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6338 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6339 rsurface.tvector3f = rsurface.modeltvector3f;
6340 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6341 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6342 rsurface.normal3f = rsurface.modelnormal3f;
6343 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6344 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6345 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6348 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
6350 dp_model_t *model = ent->model;
6351 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6353 rsurface.entity = (entity_render_t *)ent;
6354 rsurface.skeleton = ent->skeleton;
6355 rsurface.ent_skinnum = ent->skinnum;
6356 rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
6357 rsurface.ent_shadertime = ent->shadertime;
6358 rsurface.ent_flags = ent->flags;
6359 if (rsurface.array_size < model->surfmesh.num_vertices)
6360 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6361 rsurface.matrix = ent->matrix;
6362 rsurface.inversematrix = ent->inversematrix;
6363 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6364 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6365 R_Mesh_Matrix(&rsurface.matrix);
6366 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6367 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6368 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6369 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6370 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6371 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6372 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6373 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6374 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6375 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6376 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6377 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
6378 rsurface.colormod[3] = ent->alpha;
6379 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
6380 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6381 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6382 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6383 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6384 if (ent->model->brush.submodel && !prepass)
6386 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6387 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6389 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6391 if (ent->animcache_vertex3f && !r_framedata_failed)
6393 rsurface.modelvertex3f = ent->animcache_vertex3f;
6394 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
6395 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
6396 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
6398 else if (wanttangents)
6400 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6401 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6402 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6403 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6404 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6406 else if (wantnormals)
6408 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6409 rsurface.modelsvector3f = NULL;
6410 rsurface.modeltvector3f = NULL;
6411 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6412 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6416 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6417 rsurface.modelsvector3f = NULL;
6418 rsurface.modeltvector3f = NULL;
6419 rsurface.modelnormal3f = NULL;
6420 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6422 rsurface.modelvertex3f_bufferobject = 0;
6423 rsurface.modelvertex3f_bufferoffset = 0;
6424 rsurface.modelsvector3f_bufferobject = 0;
6425 rsurface.modelsvector3f_bufferoffset = 0;
6426 rsurface.modeltvector3f_bufferobject = 0;
6427 rsurface.modeltvector3f_bufferoffset = 0;
6428 rsurface.modelnormal3f_bufferobject = 0;
6429 rsurface.modelnormal3f_bufferoffset = 0;
6430 rsurface.generatedvertex = true;
6434 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6435 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6436 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6437 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6438 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6439 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6440 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6441 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6442 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6443 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6444 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6445 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6446 rsurface.generatedvertex = false;
6448 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6449 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6450 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6451 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6452 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6453 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6454 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6455 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6456 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6457 rsurface.modelelement3i = model->surfmesh.data_element3i;
6458 rsurface.modelelement3s = model->surfmesh.data_element3s;
6459 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6460 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6461 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6462 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6463 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6464 rsurface.modelsurfaces = model->data_surfaces;
6465 rsurface.vertex3f = rsurface.modelvertex3f;
6466 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6467 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6468 rsurface.svector3f = rsurface.modelsvector3f;
6469 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6470 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6471 rsurface.tvector3f = rsurface.modeltvector3f;
6472 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6473 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6474 rsurface.normal3f = rsurface.modelnormal3f;
6475 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6476 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6477 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6480 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
6482 rsurface.entity = r_refdef.scene.worldentity;
6483 rsurface.skeleton = NULL;
6484 rsurface.ent_skinnum = 0;
6485 rsurface.ent_qwskin = -1;
6486 rsurface.ent_shadertime = shadertime;
6487 rsurface.ent_flags = entflags;
6488 rsurface.modelnum_vertices = numvertices;
6489 rsurface.modelnum_triangles = numtriangles;
6490 if (rsurface.array_size < rsurface.modelnum_vertices)
6491 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6492 rsurface.matrix = *matrix;
6493 rsurface.inversematrix = *inversematrix;
6494 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6495 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6496 R_Mesh_Matrix(&rsurface.matrix);
6497 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6498 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6499 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6500 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6501 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6502 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6503 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6504 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6505 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6506 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6507 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6508 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
6509 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
6510 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6511 rsurface.frameblend[0].lerp = 1;
6512 rsurface.ent_alttextures = false;
6513 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6514 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6517 rsurface.modelvertex3f = vertex3f;
6518 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6519 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6520 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6522 else if (wantnormals)
6524 rsurface.modelvertex3f = vertex3f;
6525 rsurface.modelsvector3f = NULL;
6526 rsurface.modeltvector3f = NULL;
6527 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6531 rsurface.modelvertex3f = vertex3f;
6532 rsurface.modelsvector3f = NULL;
6533 rsurface.modeltvector3f = NULL;
6534 rsurface.modelnormal3f = NULL;
6536 rsurface.modelvertex3f_bufferobject = 0;
6537 rsurface.modelvertex3f_bufferoffset = 0;
6538 rsurface.modelsvector3f_bufferobject = 0;
6539 rsurface.modelsvector3f_bufferoffset = 0;
6540 rsurface.modeltvector3f_bufferobject = 0;
6541 rsurface.modeltvector3f_bufferoffset = 0;
6542 rsurface.modelnormal3f_bufferobject = 0;
6543 rsurface.modelnormal3f_bufferoffset = 0;
6544 rsurface.generatedvertex = true;
6545 rsurface.modellightmapcolor4f = color4f;
6546 rsurface.modellightmapcolor4f_bufferobject = 0;
6547 rsurface.modellightmapcolor4f_bufferoffset = 0;
6548 rsurface.modeltexcoordtexture2f = texcoord2f;
6549 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6550 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6551 rsurface.modeltexcoordlightmap2f = NULL;
6552 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6553 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6554 rsurface.modelelement3i = element3i;
6555 rsurface.modelelement3s = element3s;
6556 rsurface.modelelement3i_bufferobject = 0;
6557 rsurface.modelelement3s_bufferobject = 0;
6558 rsurface.modellightmapoffsets = NULL;
6559 rsurface.modelsurfaces = NULL;
6560 rsurface.vertex3f = rsurface.modelvertex3f;
6561 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6562 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6563 rsurface.svector3f = rsurface.modelsvector3f;
6564 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6565 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6566 rsurface.tvector3f = rsurface.modeltvector3f;
6567 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6568 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6569 rsurface.normal3f = rsurface.modelnormal3f;
6570 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6571 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6572 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6574 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6576 if ((wantnormals || wanttangents) && !normal3f)
6577 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6578 if (wanttangents && !svector3f)
6579 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);
6583 float RSurf_FogPoint(const float *v)
6585 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6586 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6587 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6588 float FogHeightFade = r_refdef.fogheightfade;
6590 unsigned int fogmasktableindex;
6591 if (r_refdef.fogplaneviewabove)
6592 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6594 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6595 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6596 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6599 float RSurf_FogVertex(const float *v)
6601 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6602 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6603 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6604 float FogHeightFade = rsurface.fogheightfade;
6606 unsigned int fogmasktableindex;
6607 if (r_refdef.fogplaneviewabove)
6608 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6610 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6611 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6612 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6615 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6616 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6619 int texturesurfaceindex;
6624 const float *v1, *in_tc;
6626 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6628 q3shaderinfo_deform_t *deform;
6629 // 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
6630 if (rsurface.generatedvertex)
6632 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6633 generatenormals = true;
6634 for (i = 0;i < Q3MAXDEFORMS;i++)
6636 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6638 generatetangents = true;
6639 generatenormals = true;
6641 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6642 generatenormals = true;
6644 if (generatenormals && !rsurface.modelnormal3f)
6646 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6647 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6648 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6649 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6651 if (generatetangents && !rsurface.modelsvector3f)
6653 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6654 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6655 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6656 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6657 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6658 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6659 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);
6662 rsurface.vertex3f = rsurface.modelvertex3f;
6663 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6664 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6665 rsurface.svector3f = rsurface.modelsvector3f;
6666 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6667 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6668 rsurface.tvector3f = rsurface.modeltvector3f;
6669 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6670 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6671 rsurface.normal3f = rsurface.modelnormal3f;
6672 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6673 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6674 // if vertices are deformed (sprite flares and things in maps, possibly
6675 // water waves, bulges and other deformations), generate them into
6676 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6677 // (may be static model data or generated data for an animated model, or
6678 // the previous deform pass)
6679 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6681 switch (deform->deform)
6684 case Q3DEFORM_PROJECTIONSHADOW:
6685 case Q3DEFORM_TEXT0:
6686 case Q3DEFORM_TEXT1:
6687 case Q3DEFORM_TEXT2:
6688 case Q3DEFORM_TEXT3:
6689 case Q3DEFORM_TEXT4:
6690 case Q3DEFORM_TEXT5:
6691 case Q3DEFORM_TEXT6:
6692 case Q3DEFORM_TEXT7:
6695 case Q3DEFORM_AUTOSPRITE:
6696 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6697 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6698 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6699 VectorNormalize(newforward);
6700 VectorNormalize(newright);
6701 VectorNormalize(newup);
6702 // make deformed versions of only the model vertices used by the specified surfaces
6703 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6705 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6706 // a single autosprite surface can contain multiple sprites...
6707 for (j = 0;j < surface->num_vertices - 3;j += 4)
6709 VectorClear(center);
6710 for (i = 0;i < 4;i++)
6711 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6712 VectorScale(center, 0.25f, center);
6713 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6714 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6715 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6716 for (i = 0;i < 4;i++)
6718 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6719 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6722 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);
6723 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);
6725 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6726 rsurface.vertex3f_bufferobject = 0;
6727 rsurface.vertex3f_bufferoffset = 0;
6728 rsurface.svector3f = rsurface.array_deformedsvector3f;
6729 rsurface.svector3f_bufferobject = 0;
6730 rsurface.svector3f_bufferoffset = 0;
6731 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6732 rsurface.tvector3f_bufferobject = 0;
6733 rsurface.tvector3f_bufferoffset = 0;
6734 rsurface.normal3f = rsurface.array_deformednormal3f;
6735 rsurface.normal3f_bufferobject = 0;
6736 rsurface.normal3f_bufferoffset = 0;
6738 case Q3DEFORM_AUTOSPRITE2:
6739 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6740 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6741 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6742 VectorNormalize(newforward);
6743 VectorNormalize(newright);
6744 VectorNormalize(newup);
6745 // make deformed versions of only the model vertices used by the specified surfaces
6746 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6748 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6749 const float *v1, *v2;
6759 memset(shortest, 0, sizeof(shortest));
6760 // a single autosprite surface can contain multiple sprites...
6761 for (j = 0;j < surface->num_vertices - 3;j += 4)
6763 VectorClear(center);
6764 for (i = 0;i < 4;i++)
6765 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6766 VectorScale(center, 0.25f, center);
6767 // find the two shortest edges, then use them to define the
6768 // axis vectors for rotating around the central axis
6769 for (i = 0;i < 6;i++)
6771 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6772 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6774 Debug_PolygonBegin(NULL, 0);
6775 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6776 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);
6777 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6780 l = VectorDistance2(v1, v2);
6781 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6783 l += (1.0f / 1024.0f);
6784 if (shortest[0].length2 > l || i == 0)
6786 shortest[1] = shortest[0];
6787 shortest[0].length2 = l;
6788 shortest[0].v1 = v1;
6789 shortest[0].v2 = v2;
6791 else if (shortest[1].length2 > l || i == 1)
6793 shortest[1].length2 = l;
6794 shortest[1].v1 = v1;
6795 shortest[1].v2 = v2;
6798 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6799 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6801 Debug_PolygonBegin(NULL, 0);
6802 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6803 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);
6804 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6807 // this calculates the right vector from the shortest edge
6808 // and the up vector from the edge midpoints
6809 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6810 VectorNormalize(right);
6811 VectorSubtract(end, start, up);
6812 VectorNormalize(up);
6813 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6814 VectorSubtract(rsurface.localvieworigin, center, forward);
6815 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6816 VectorNegate(forward, forward);
6817 VectorReflect(forward, 0, up, forward);
6818 VectorNormalize(forward);
6819 CrossProduct(up, forward, newright);
6820 VectorNormalize(newright);
6822 Debug_PolygonBegin(NULL, 0);
6823 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);
6824 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6825 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6829 Debug_PolygonBegin(NULL, 0);
6830 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6831 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6832 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6835 // rotate the quad around the up axis vector, this is made
6836 // especially easy by the fact we know the quad is flat,
6837 // so we only have to subtract the center position and
6838 // measure distance along the right vector, and then
6839 // multiply that by the newright vector and add back the
6841 // we also need to subtract the old position to undo the
6842 // displacement from the center, which we do with a
6843 // DotProduct, the subtraction/addition of center is also
6844 // optimized into DotProducts here
6845 l = DotProduct(right, center);
6846 for (i = 0;i < 4;i++)
6848 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6849 f = DotProduct(right, v1) - l;
6850 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6853 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);
6854 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);
6856 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6857 rsurface.vertex3f_bufferobject = 0;
6858 rsurface.vertex3f_bufferoffset = 0;
6859 rsurface.svector3f = rsurface.array_deformedsvector3f;
6860 rsurface.svector3f_bufferobject = 0;
6861 rsurface.svector3f_bufferoffset = 0;
6862 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6863 rsurface.tvector3f_bufferobject = 0;
6864 rsurface.tvector3f_bufferoffset = 0;
6865 rsurface.normal3f = rsurface.array_deformednormal3f;
6866 rsurface.normal3f_bufferobject = 0;
6867 rsurface.normal3f_bufferoffset = 0;
6869 case Q3DEFORM_NORMAL:
6870 // deform the normals to make reflections wavey
6871 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6873 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6874 for (j = 0;j < surface->num_vertices;j++)
6877 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6878 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6879 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6880 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6881 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6882 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6883 VectorNormalize(normal);
6885 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);
6887 rsurface.svector3f = rsurface.array_deformedsvector3f;
6888 rsurface.svector3f_bufferobject = 0;
6889 rsurface.svector3f_bufferoffset = 0;
6890 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6891 rsurface.tvector3f_bufferobject = 0;
6892 rsurface.tvector3f_bufferoffset = 0;
6893 rsurface.normal3f = rsurface.array_deformednormal3f;
6894 rsurface.normal3f_bufferobject = 0;
6895 rsurface.normal3f_bufferoffset = 0;
6898 // deform vertex array to make wavey water and flags and such
6899 waveparms[0] = deform->waveparms[0];
6900 waveparms[1] = deform->waveparms[1];
6901 waveparms[2] = deform->waveparms[2];
6902 waveparms[3] = deform->waveparms[3];
6903 // this is how a divisor of vertex influence on deformation
6904 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6905 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6906 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6908 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6909 for (j = 0;j < surface->num_vertices;j++)
6911 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6912 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6913 // if the wavefunc depends on time, evaluate it per-vertex
6916 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6917 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6919 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6922 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6923 rsurface.vertex3f_bufferobject = 0;
6924 rsurface.vertex3f_bufferoffset = 0;
6926 case Q3DEFORM_BULGE:
6927 // deform vertex array to make the surface have moving bulges
6928 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6930 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6931 for (j = 0;j < surface->num_vertices;j++)
6933 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6934 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6937 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6938 rsurface.vertex3f_bufferobject = 0;
6939 rsurface.vertex3f_bufferoffset = 0;
6942 // deform vertex array
6943 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6944 VectorScale(deform->parms, scale, waveparms);
6945 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6947 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6948 for (j = 0;j < surface->num_vertices;j++)
6949 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6951 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6952 rsurface.vertex3f_bufferobject = 0;
6953 rsurface.vertex3f_bufferoffset = 0;
6957 // generate texcoords based on the chosen texcoord source
6958 switch(rsurface.texture->tcgen.tcgen)
6961 case Q3TCGEN_TEXTURE:
6962 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6963 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6964 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6966 case Q3TCGEN_LIGHTMAP:
6967 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6968 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6969 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6971 case Q3TCGEN_VECTOR:
6972 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6974 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6975 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)
6977 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6978 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6981 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6982 rsurface.texcoordtexture2f_bufferobject = 0;
6983 rsurface.texcoordtexture2f_bufferoffset = 0;
6985 case Q3TCGEN_ENVIRONMENT:
6986 // make environment reflections using a spheremap
6987 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6989 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6990 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6991 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6992 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6993 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6995 // identical to Q3A's method, but executed in worldspace so
6996 // carried models can be shiny too
6998 float viewer[3], d, reflected[3], worldreflected[3];
7000 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
7001 // VectorNormalize(viewer);
7003 d = DotProduct(normal, viewer);
7005 reflected[0] = normal[0]*2*d - viewer[0];
7006 reflected[1] = normal[1]*2*d - viewer[1];
7007 reflected[2] = normal[2]*2*d - viewer[2];
7008 // note: this is proportinal to viewer, so we can normalize later
7010 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7011 VectorNormalize(worldreflected);
7013 // note: this sphere map only uses world x and z!
7014 // so positive and negative y will LOOK THE SAME.
7015 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7016 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7019 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7020 rsurface.texcoordtexture2f_bufferobject = 0;
7021 rsurface.texcoordtexture2f_bufferoffset = 0;
7024 // the only tcmod that needs software vertex processing is turbulent, so
7025 // check for it here and apply the changes if needed
7026 // and we only support that as the first one
7027 // (handling a mixture of turbulent and other tcmods would be problematic
7028 // without punting it entirely to a software path)
7029 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7031 amplitude = rsurface.texture->tcmods[0].parms[1];
7032 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7033 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7035 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7036 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)
7038 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7039 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7042 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7043 rsurface.texcoordtexture2f_bufferobject = 0;
7044 rsurface.texcoordtexture2f_bufferoffset = 0;
7046 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7047 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7048 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7049 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7052 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7055 const msurface_t *surface = texturesurfacelist[0];
7056 const msurface_t *surface2;
7061 // TODO: lock all array ranges before render, rather than on each surface
7062 if (texturenumsurfaces == 1)
7064 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7065 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);
7067 else if (r_batchmode.integer == 2)
7069 #define MAXBATCHTRIANGLES 4096
7070 int batchtriangles = 0;
7071 int batchelements[MAXBATCHTRIANGLES*3];
7072 for (i = 0;i < texturenumsurfaces;i = j)
7074 surface = texturesurfacelist[i];
7076 if (surface->num_triangles > MAXBATCHTRIANGLES)
7078 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);
7081 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7082 batchtriangles = surface->num_triangles;
7083 firstvertex = surface->num_firstvertex;
7084 endvertex = surface->num_firstvertex + surface->num_vertices;
7085 for (;j < texturenumsurfaces;j++)
7087 surface2 = texturesurfacelist[j];
7088 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7090 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7091 batchtriangles += surface2->num_triangles;
7092 firstvertex = min(firstvertex, surface2->num_firstvertex);
7093 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7095 surface2 = texturesurfacelist[j-1];
7096 numvertices = endvertex - firstvertex;
7097 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7100 else if (r_batchmode.integer == 1)
7102 for (i = 0;i < texturenumsurfaces;i = j)
7104 surface = texturesurfacelist[i];
7105 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7106 if (texturesurfacelist[j] != surface2)
7108 surface2 = texturesurfacelist[j-1];
7109 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7110 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7111 GL_LockArrays(surface->num_firstvertex, numvertices);
7112 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7117 for (i = 0;i < texturenumsurfaces;i++)
7119 surface = texturesurfacelist[i];
7120 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7121 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);
7126 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
7128 int i, planeindex, vertexindex;
7132 r_waterstate_waterplane_t *p, *bestp;
7133 const msurface_t *surface;
7134 if (r_waterstate.renderingscene)
7136 for (i = 0;i < texturenumsurfaces;i++)
7138 surface = texturesurfacelist[i];
7139 if (lightmaptexunit >= 0)
7140 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7141 if (deluxemaptexunit >= 0)
7142 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7143 // pick the closest matching water plane
7146 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7149 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7151 Matrix4x4_Transform(&rsurface.matrix, v, vert);
7152 d += fabs(PlaneDiff(vert, &p->plane));
7154 if (bestd > d || !bestp)
7162 if (refractiontexunit >= 0)
7163 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
7164 if (reflectiontexunit >= 0)
7165 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
7169 if (refractiontexunit >= 0)
7170 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
7171 if (reflectiontexunit >= 0)
7172 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
7174 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7175 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);
7179 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
7183 const msurface_t *surface = texturesurfacelist[0];
7184 const msurface_t *surface2;
7189 // TODO: lock all array ranges before render, rather than on each surface
7190 if (texturenumsurfaces == 1)
7192 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7193 if (deluxemaptexunit >= 0)
7194 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7195 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7196 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);
7198 else if (r_batchmode.integer == 2)
7200 #define MAXBATCHTRIANGLES 4096
7201 int batchtriangles = 0;
7202 int batchelements[MAXBATCHTRIANGLES*3];
7203 for (i = 0;i < texturenumsurfaces;i = j)
7205 surface = texturesurfacelist[i];
7206 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7207 if (deluxemaptexunit >= 0)
7208 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7210 if (surface->num_triangles > MAXBATCHTRIANGLES)
7212 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);
7215 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7216 batchtriangles = surface->num_triangles;
7217 firstvertex = surface->num_firstvertex;
7218 endvertex = surface->num_firstvertex + surface->num_vertices;
7219 for (;j < texturenumsurfaces;j++)
7221 surface2 = texturesurfacelist[j];
7222 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7224 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7225 batchtriangles += surface2->num_triangles;
7226 firstvertex = min(firstvertex, surface2->num_firstvertex);
7227 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7229 surface2 = texturesurfacelist[j-1];
7230 numvertices = endvertex - firstvertex;
7231 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7234 else if (r_batchmode.integer == 1)
7237 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
7238 for (i = 0;i < texturenumsurfaces;i = j)
7240 surface = texturesurfacelist[i];
7241 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7242 if (texturesurfacelist[j] != surface2)
7244 Con_Printf(" %i", j - i);
7247 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
7249 for (i = 0;i < texturenumsurfaces;i = j)
7251 surface = texturesurfacelist[i];
7252 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7253 if (deluxemaptexunit >= 0)
7254 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7255 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7256 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7259 Con_Printf(" %i", j - i);
7261 surface2 = texturesurfacelist[j-1];
7262 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7263 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7264 GL_LockArrays(surface->num_firstvertex, numvertices);
7265 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7273 for (i = 0;i < texturenumsurfaces;i++)
7275 surface = texturesurfacelist[i];
7276 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7277 if (deluxemaptexunit >= 0)
7278 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7279 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7280 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);
7285 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7288 int texturesurfaceindex;
7289 if (r_showsurfaces.integer == 2)
7291 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7293 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7294 for (j = 0;j < surface->num_triangles;j++)
7296 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7297 GL_Color(f, f, f, 1);
7298 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7304 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7306 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7307 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7308 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);
7309 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7310 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);
7315 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7317 int texturesurfaceindex;
7321 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7323 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7324 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)
7332 rsurface.lightmapcolor4f = rsurface.array_color4f;
7333 rsurface.lightmapcolor4f_bufferobject = 0;
7334 rsurface.lightmapcolor4f_bufferoffset = 0;
7337 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7339 int texturesurfaceindex;
7345 if (rsurface.lightmapcolor4f)
7347 // generate color arrays for the surfaces in this list
7348 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7350 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7351 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)
7353 f = RSurf_FogVertex(v);
7363 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7365 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7366 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)
7368 f = RSurf_FogVertex(v);
7376 rsurface.lightmapcolor4f = rsurface.array_color4f;
7377 rsurface.lightmapcolor4f_bufferobject = 0;
7378 rsurface.lightmapcolor4f_bufferoffset = 0;
7381 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7383 int texturesurfaceindex;
7389 if (!rsurface.lightmapcolor4f)
7391 // generate color arrays for the surfaces in this list
7392 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7394 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7395 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)
7397 f = RSurf_FogVertex(v);
7398 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7399 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7400 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7404 rsurface.lightmapcolor4f = rsurface.array_color4f;
7405 rsurface.lightmapcolor4f_bufferobject = 0;
7406 rsurface.lightmapcolor4f_bufferoffset = 0;
7409 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7411 int texturesurfaceindex;
7415 if (!rsurface.lightmapcolor4f)
7417 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7419 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7420 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)
7428 rsurface.lightmapcolor4f = rsurface.array_color4f;
7429 rsurface.lightmapcolor4f_bufferobject = 0;
7430 rsurface.lightmapcolor4f_bufferoffset = 0;
7433 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7435 int texturesurfaceindex;
7439 if (!rsurface.lightmapcolor4f)
7441 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7443 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7444 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)
7446 c2[0] = c[0] + r_refdef.scene.ambient;
7447 c2[1] = c[1] + r_refdef.scene.ambient;
7448 c2[2] = c[2] + r_refdef.scene.ambient;
7452 rsurface.lightmapcolor4f = rsurface.array_color4f;
7453 rsurface.lightmapcolor4f_bufferobject = 0;
7454 rsurface.lightmapcolor4f_bufferoffset = 0;
7457 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7460 rsurface.lightmapcolor4f = NULL;
7461 rsurface.lightmapcolor4f_bufferobject = 0;
7462 rsurface.lightmapcolor4f_bufferoffset = 0;
7463 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7464 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7465 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7466 GL_Color(r, g, b, a);
7467 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7470 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7472 // TODO: optimize applyfog && applycolor case
7473 // just apply fog if necessary, and tint the fog color array if necessary
7474 rsurface.lightmapcolor4f = NULL;
7475 rsurface.lightmapcolor4f_bufferobject = 0;
7476 rsurface.lightmapcolor4f_bufferoffset = 0;
7477 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7478 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7479 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7480 GL_Color(r, g, b, a);
7481 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7484 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7486 int texturesurfaceindex;
7490 if (texturesurfacelist[0]->lightmapinfo)
7492 // generate color arrays for the surfaces in this list
7493 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7495 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7496 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7498 if (surface->lightmapinfo->samples)
7500 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7501 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7502 VectorScale(lm, scale, c);
7503 if (surface->lightmapinfo->styles[1] != 255)
7505 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7507 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7508 VectorMA(c, scale, lm, c);
7509 if (surface->lightmapinfo->styles[2] != 255)
7512 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7513 VectorMA(c, scale, lm, c);
7514 if (surface->lightmapinfo->styles[3] != 255)
7517 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7518 VectorMA(c, scale, lm, c);
7528 rsurface.lightmapcolor4f = rsurface.array_color4f;
7529 rsurface.lightmapcolor4f_bufferobject = 0;
7530 rsurface.lightmapcolor4f_bufferoffset = 0;
7534 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7535 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7536 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7538 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7539 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7540 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7541 GL_Color(r, g, b, a);
7542 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7545 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7547 int texturesurfaceindex;
7554 vec3_t ambientcolor;
7555 vec3_t diffusecolor;
7559 VectorCopy(rsurface.modellight_lightdir, lightdir);
7560 f = 0.5f * r_refdef.lightmapintensity;
7561 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7562 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7563 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7564 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7565 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7566 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7568 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7570 // generate color arrays for the surfaces in this list
7571 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7573 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7574 int numverts = surface->num_vertices;
7575 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7576 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7577 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7578 // q3-style directional shading
7579 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7581 if ((f = DotProduct(n, lightdir)) > 0)
7582 VectorMA(ambientcolor, f, diffusecolor, c);
7584 VectorCopy(ambientcolor, c);
7592 rsurface.lightmapcolor4f = rsurface.array_color4f;
7593 rsurface.lightmapcolor4f_bufferobject = 0;
7594 rsurface.lightmapcolor4f_bufferoffset = 0;
7595 *applycolor = false;
7599 *r = ambientcolor[0];
7600 *g = ambientcolor[1];
7601 *b = ambientcolor[2];
7602 rsurface.lightmapcolor4f = NULL;
7603 rsurface.lightmapcolor4f_bufferobject = 0;
7604 rsurface.lightmapcolor4f_bufferoffset = 0;
7608 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7610 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7611 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7612 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7613 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7614 GL_Color(r, g, b, a);
7615 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7618 void RSurf_SetupDepthAndCulling(void)
7620 // submodels are biased to avoid z-fighting with world surfaces that they
7621 // may be exactly overlapping (avoids z-fighting artifacts on certain
7622 // doors and things in Quake maps)
7623 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7624 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7625 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7626 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7629 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7631 // transparent sky would be ridiculous
7632 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7634 R_SetupGenericShader(false);
7635 skyrenderlater = true;
7636 RSurf_SetupDepthAndCulling();
7638 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7639 // skymasking on them, and Quake3 never did sky masking (unlike
7640 // software Quake and software Quake2), so disable the sky masking
7641 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7642 // and skymasking also looks very bad when noclipping outside the
7643 // level, so don't use it then either.
7644 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7646 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7647 R_Mesh_ColorPointer(NULL, 0, 0);
7648 R_Mesh_ResetTextureState();
7649 if (skyrendermasked)
7651 R_SetupDepthOrShadowShader();
7652 // depth-only (masking)
7653 GL_ColorMask(0,0,0,0);
7654 // just to make sure that braindead drivers don't draw
7655 // anything despite that colormask...
7656 GL_BlendFunc(GL_ZERO, GL_ONE);
7660 R_SetupGenericShader(false);
7662 GL_BlendFunc(GL_ONE, GL_ZERO);
7664 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7665 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7666 if (skyrendermasked)
7667 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7669 R_Mesh_ResetTextureState();
7670 GL_Color(1, 1, 1, 1);
7673 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
7674 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
7675 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
7677 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7680 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7681 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7682 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7683 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7684 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7685 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7686 if (rsurface.texture->backgroundcurrentskinframe)
7688 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7689 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7690 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7691 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7693 if (rsurface.texture->colormapping)
7695 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7696 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7698 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7699 if (r_shadow_usingdeferredprepass)
7701 R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture));
7702 R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture));
7704 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7705 R_Mesh_ColorPointer(NULL, 0, 0);
7707 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7709 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass)
7711 // render background
7712 GL_BlendFunc(GL_ONE, GL_ZERO);
7714 GL_AlphaTest(false);
7716 GL_Color(1, 1, 1, 1);
7717 R_Mesh_ColorPointer(NULL, 0, 0);
7719 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7720 if (r_glsl_permutation)
7722 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7723 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7724 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7725 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7726 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7727 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7728 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);
7730 GL_LockArrays(0, 0);
7732 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7733 GL_DepthMask(false);
7734 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7735 R_Mesh_ColorPointer(NULL, 0, 0);
7737 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7738 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7739 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7742 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
7743 if (!r_glsl_permutation)
7746 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7747 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7748 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7749 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7750 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7752 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7754 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7756 GL_BlendFunc(GL_ONE, GL_ZERO);
7758 GL_AlphaTest(false);
7762 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7763 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7764 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
7767 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7769 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7770 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);
7772 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7776 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7777 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);
7779 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7781 GL_LockArrays(0, 0);
7784 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7786 // OpenGL 1.3 path - anything not completely ancient
7787 int texturesurfaceindex;
7788 qboolean applycolor;
7792 const texturelayer_t *layer;
7793 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7795 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7798 int layertexrgbscale;
7799 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7801 if (layerindex == 0)
7805 GL_AlphaTest(false);
7806 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7809 GL_DepthMask(layer->depthmask && writedepth);
7810 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7811 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7813 layertexrgbscale = 4;
7814 VectorScale(layer->color, 0.25f, layercolor);
7816 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7818 layertexrgbscale = 2;
7819 VectorScale(layer->color, 0.5f, layercolor);
7823 layertexrgbscale = 1;
7824 VectorScale(layer->color, 1.0f, layercolor);
7826 layercolor[3] = layer->color[3];
7827 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7828 R_Mesh_ColorPointer(NULL, 0, 0);
7829 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7830 switch (layer->type)
7832 case TEXTURELAYERTYPE_LITTEXTURE:
7833 memset(&m, 0, sizeof(m));
7834 m.tex[0] = R_GetTexture(r_texture_white);
7835 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7836 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7837 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7838 m.tex[1] = R_GetTexture(layer->texture);
7839 m.texmatrix[1] = layer->texmatrix;
7840 m.texrgbscale[1] = layertexrgbscale;
7841 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7842 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7843 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7844 R_Mesh_TextureState(&m);
7845 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7846 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7847 else if (rsurface.uselightmaptexture)
7848 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7850 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7852 case TEXTURELAYERTYPE_TEXTURE:
7853 memset(&m, 0, sizeof(m));
7854 m.tex[0] = R_GetTexture(layer->texture);
7855 m.texmatrix[0] = layer->texmatrix;
7856 m.texrgbscale[0] = layertexrgbscale;
7857 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7858 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7859 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7860 R_Mesh_TextureState(&m);
7861 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7863 case TEXTURELAYERTYPE_FOG:
7864 memset(&m, 0, sizeof(m));
7865 m.texrgbscale[0] = layertexrgbscale;
7868 m.tex[0] = R_GetTexture(layer->texture);
7869 m.texmatrix[0] = layer->texmatrix;
7870 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7871 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7872 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7874 R_Mesh_TextureState(&m);
7875 // generate a color array for the fog pass
7876 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7877 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7883 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7884 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)
7886 f = 1 - RSurf_FogVertex(v);
7887 c[0] = layercolor[0];
7888 c[1] = layercolor[1];
7889 c[2] = layercolor[2];
7890 c[3] = f * layercolor[3];
7893 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7896 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7898 GL_LockArrays(0, 0);
7901 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7903 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7904 GL_AlphaTest(false);
7908 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7910 // OpenGL 1.1 - crusty old voodoo path
7911 int texturesurfaceindex;
7915 const texturelayer_t *layer;
7916 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7918 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7920 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7922 if (layerindex == 0)
7926 GL_AlphaTest(false);
7927 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7930 GL_DepthMask(layer->depthmask && writedepth);
7931 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7932 R_Mesh_ColorPointer(NULL, 0, 0);
7933 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7934 switch (layer->type)
7936 case TEXTURELAYERTYPE_LITTEXTURE:
7937 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7939 // two-pass lit texture with 2x rgbscale
7940 // first the lightmap pass
7941 memset(&m, 0, sizeof(m));
7942 m.tex[0] = R_GetTexture(r_texture_white);
7943 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7944 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7945 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7946 R_Mesh_TextureState(&m);
7947 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7948 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7949 else if (rsurface.uselightmaptexture)
7950 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7952 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7953 GL_LockArrays(0, 0);
7954 // then apply the texture to it
7955 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7956 memset(&m, 0, sizeof(m));
7957 m.tex[0] = R_GetTexture(layer->texture);
7958 m.texmatrix[0] = layer->texmatrix;
7959 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7960 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7961 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7962 R_Mesh_TextureState(&m);
7963 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);
7967 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7968 memset(&m, 0, sizeof(m));
7969 m.tex[0] = R_GetTexture(layer->texture);
7970 m.texmatrix[0] = layer->texmatrix;
7971 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7972 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7973 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7974 R_Mesh_TextureState(&m);
7975 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7976 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);
7978 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);
7981 case TEXTURELAYERTYPE_TEXTURE:
7982 // singletexture unlit texture with transparency support
7983 memset(&m, 0, sizeof(m));
7984 m.tex[0] = R_GetTexture(layer->texture);
7985 m.texmatrix[0] = layer->texmatrix;
7986 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7987 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7988 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7989 R_Mesh_TextureState(&m);
7990 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);
7992 case TEXTURELAYERTYPE_FOG:
7993 // singletexture fogging
7994 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7997 memset(&m, 0, sizeof(m));
7998 m.tex[0] = R_GetTexture(layer->texture);
7999 m.texmatrix[0] = layer->texmatrix;
8000 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
8001 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
8002 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
8003 R_Mesh_TextureState(&m);
8006 R_Mesh_ResetTextureState();
8007 // generate a color array for the fog pass
8008 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8014 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8015 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)
8017 f = 1 - RSurf_FogVertex(v);
8018 c[0] = layer->color[0];
8019 c[1] = layer->color[1];
8020 c[2] = layer->color[2];
8021 c[3] = f * layer->color[3];
8024 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8027 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8029 GL_LockArrays(0, 0);
8032 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8034 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8035 GL_AlphaTest(false);
8039 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8043 GL_AlphaTest(false);
8044 R_Mesh_ColorPointer(NULL, 0, 0);
8045 R_Mesh_ResetTextureState();
8046 R_SetupGenericShader(false);
8048 if(rsurface.texture && rsurface.texture->currentskinframe)
8050 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8051 c[3] *= rsurface.texture->currentalpha;
8061 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
8063 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8064 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8065 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8068 // brighten it up (as texture value 127 means "unlit")
8069 c[0] *= 2 * r_refdef.view.colorscale;
8070 c[1] *= 2 * r_refdef.view.colorscale;
8071 c[2] *= 2 * r_refdef.view.colorscale;
8073 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8074 c[3] *= r_wateralpha.value;
8076 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8078 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8079 GL_DepthMask(false);
8081 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8083 GL_BlendFunc(GL_ONE, GL_ONE);
8084 GL_DepthMask(false);
8086 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8088 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8089 GL_DepthMask(false);
8091 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8093 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8094 GL_DepthMask(false);
8098 GL_BlendFunc(GL_ONE, GL_ZERO);
8099 GL_DepthMask(writedepth);
8102 rsurface.lightmapcolor4f = NULL;
8104 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8106 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8108 rsurface.lightmapcolor4f = NULL;
8109 rsurface.lightmapcolor4f_bufferobject = 0;
8110 rsurface.lightmapcolor4f_bufferoffset = 0;
8112 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8114 qboolean applycolor = true;
8117 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8119 r_refdef.lightmapintensity = 1;
8120 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8121 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8125 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8127 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8128 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8129 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8132 if(!rsurface.lightmapcolor4f)
8133 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8135 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8136 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8137 if(r_refdef.fogenabled)
8138 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8140 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8141 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8144 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8147 RSurf_SetupDepthAndCulling();
8148 if (r_showsurfaces.integer == 3 && !prepass)
8150 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8153 switch (vid.renderpath)
8155 case RENDERPATH_GL20:
8156 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8158 case RENDERPATH_GL13:
8159 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8161 case RENDERPATH_GL11:
8162 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8168 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8171 RSurf_SetupDepthAndCulling();
8172 if (r_showsurfaces.integer == 3 && !prepass)
8174 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8177 switch (vid.renderpath)
8179 case RENDERPATH_GL20:
8180 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8182 case RENDERPATH_GL13:
8183 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8185 case RENDERPATH_GL11:
8186 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8192 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8195 int texturenumsurfaces, endsurface;
8197 const msurface_t *surface;
8198 const msurface_t *texturesurfacelist[1024];
8200 // if the model is static it doesn't matter what value we give for
8201 // wantnormals and wanttangents, so this logic uses only rules applicable
8202 // to a model, knowing that they are meaningless otherwise
8203 if (ent == r_refdef.scene.worldentity)
8204 RSurf_ActiveWorldEntity();
8205 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8206 RSurf_ActiveModelEntity(ent, false, false, false);
8209 switch (vid.renderpath)
8211 case RENDERPATH_GL20:
8212 RSurf_ActiveModelEntity(ent, true, true, false);
8214 case RENDERPATH_GL13:
8215 case RENDERPATH_GL11:
8216 RSurf_ActiveModelEntity(ent, true, false, false);
8221 if (r_transparentdepthmasking.integer)
8223 qboolean setup = false;
8224 for (i = 0;i < numsurfaces;i = j)
8227 surface = rsurface.modelsurfaces + surfacelist[i];
8228 texture = surface->texture;
8229 rsurface.texture = R_GetCurrentTexture(texture);
8230 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8231 // scan ahead until we find a different texture
8232 endsurface = min(i + 1024, numsurfaces);
8233 texturenumsurfaces = 0;
8234 texturesurfacelist[texturenumsurfaces++] = surface;
8235 for (;j < endsurface;j++)
8237 surface = rsurface.modelsurfaces + surfacelist[j];
8238 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8240 texturesurfacelist[texturenumsurfaces++] = surface;
8242 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
8244 // render the range of surfaces as depth
8248 GL_ColorMask(0,0,0,0);
8251 GL_BlendFunc(GL_ONE, GL_ZERO);
8253 GL_AlphaTest(false);
8254 R_Mesh_ColorPointer(NULL, 0, 0);
8255 R_Mesh_ResetTextureState();
8256 R_SetupDepthOrShadowShader();
8258 RSurf_SetupDepthAndCulling();
8259 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8260 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8263 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8266 for (i = 0;i < numsurfaces;i = j)
8269 surface = rsurface.modelsurfaces + surfacelist[i];
8270 texture = surface->texture;
8271 rsurface.texture = R_GetCurrentTexture(texture);
8272 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8273 // scan ahead until we find a different texture
8274 endsurface = min(i + 1024, numsurfaces);
8275 texturenumsurfaces = 0;
8276 texturesurfacelist[texturenumsurfaces++] = surface;
8277 for (;j < endsurface;j++)
8279 surface = rsurface.modelsurfaces + surfacelist[j];
8280 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8282 texturesurfacelist[texturenumsurfaces++] = surface;
8284 // render the range of surfaces
8285 if (ent == r_refdef.scene.worldentity)
8286 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8288 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8290 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8291 GL_AlphaTest(false);
8294 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
8296 // transparent surfaces get pushed off into the transparent queue
8297 int surfacelistindex;
8298 const msurface_t *surface;
8299 vec3_t tempcenter, center;
8300 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8302 surface = texturesurfacelist[surfacelistindex];
8303 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8304 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8305 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8306 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8307 if (queueentity->transparent_offset) // transparent offset
8309 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8310 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8311 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8313 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8317 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
8319 const entity_render_t *queueentity = r_refdef.scene.worldentity;
8323 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8325 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8327 RSurf_SetupDepthAndCulling();
8328 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8329 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8333 if (!rsurface.texture->currentnumlayers)
8335 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8336 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8338 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8340 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
8342 RSurf_SetupDepthAndCulling();
8343 GL_AlphaTest(false);
8344 R_Mesh_ColorPointer(NULL, 0, 0);
8345 R_Mesh_ResetTextureState();
8346 R_SetupGenericShader(false);
8347 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8349 GL_BlendFunc(GL_ONE, GL_ZERO);
8350 GL_Color(0, 0, 0, 1);
8351 GL_DepthTest(writedepth);
8352 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8354 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
8356 RSurf_SetupDepthAndCulling();
8357 GL_AlphaTest(false);
8358 R_Mesh_ColorPointer(NULL, 0, 0);
8359 R_Mesh_ResetTextureState();
8360 R_SetupGenericShader(false);
8361 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8363 GL_BlendFunc(GL_ONE, GL_ZERO);
8365 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8367 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8368 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8369 else if (!rsurface.texture->currentnumlayers)
8371 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8373 // in the deferred case, transparent surfaces were queued during prepass
8374 if (!r_shadow_usingdeferredprepass)
8375 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8379 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8380 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8385 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8389 // break the surface list down into batches by texture and use of lightmapping
8390 for (i = 0;i < numsurfaces;i = j)
8393 // texture is the base texture pointer, rsurface.texture is the
8394 // current frame/skin the texture is directing us to use (for example
8395 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8396 // use skin 1 instead)
8397 texture = surfacelist[i]->texture;
8398 rsurface.texture = R_GetCurrentTexture(texture);
8399 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8400 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8402 // if this texture is not the kind we want, skip ahead to the next one
8403 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8407 // simply scan ahead until we find a different texture or lightmap state
8408 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8410 // render the range of surfaces
8411 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
8415 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
8420 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8422 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8424 RSurf_SetupDepthAndCulling();
8425 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8426 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8430 if (!rsurface.texture->currentnumlayers)
8432 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8433 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8435 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8437 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8439 RSurf_SetupDepthAndCulling();
8440 GL_AlphaTest(false);
8441 R_Mesh_ColorPointer(NULL, 0, 0);
8442 R_Mesh_ResetTextureState();
8443 R_SetupGenericShader(false);
8444 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8446 GL_BlendFunc(GL_ONE, GL_ZERO);
8447 GL_Color(0, 0, 0, 1);
8448 GL_DepthTest(writedepth);
8449 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8451 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8453 RSurf_SetupDepthAndCulling();
8454 GL_AlphaTest(false);
8455 R_Mesh_ColorPointer(NULL, 0, 0);
8456 R_Mesh_ResetTextureState();
8457 R_SetupGenericShader(false);
8458 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8460 GL_BlendFunc(GL_ONE, GL_ZERO);
8462 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8464 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8465 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8466 else if (!rsurface.texture->currentnumlayers)
8468 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8470 // in the deferred case, transparent surfaces were queued during prepass
8471 if (!r_shadow_usingdeferredprepass)
8472 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8476 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8477 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8482 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8486 // break the surface list down into batches by texture and use of lightmapping
8487 for (i = 0;i < numsurfaces;i = j)
8490 // texture is the base texture pointer, rsurface.texture is the
8491 // current frame/skin the texture is directing us to use (for example
8492 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8493 // use skin 1 instead)
8494 texture = surfacelist[i]->texture;
8495 rsurface.texture = R_GetCurrentTexture(texture);
8496 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8497 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8499 // if this texture is not the kind we want, skip ahead to the next one
8500 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8504 // simply scan ahead until we find a different texture or lightmap state
8505 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8507 // render the range of surfaces
8508 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
8512 float locboxvertex3f[6*4*3] =
8514 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8515 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8516 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8517 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8518 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8519 1,0,0, 0,0,0, 0,1,0, 1,1,0
8522 unsigned short locboxelements[6*2*3] =
8532 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8535 cl_locnode_t *loc = (cl_locnode_t *)ent;
8537 float vertex3f[6*4*3];
8539 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8540 GL_DepthMask(false);
8541 GL_DepthRange(0, 1);
8542 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8544 GL_CullFace(GL_NONE);
8545 R_Mesh_Matrix(&identitymatrix);
8547 R_Mesh_VertexPointer(vertex3f, 0, 0);
8548 R_Mesh_ColorPointer(NULL, 0, 0);
8549 R_Mesh_ResetTextureState();
8550 R_SetupGenericShader(false);
8553 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8554 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8555 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8556 surfacelist[0] < 0 ? 0.5f : 0.125f);
8558 if (VectorCompare(loc->mins, loc->maxs))
8560 VectorSet(size, 2, 2, 2);
8561 VectorMA(loc->mins, -0.5f, size, mins);
8565 VectorCopy(loc->mins, mins);
8566 VectorSubtract(loc->maxs, loc->mins, size);
8569 for (i = 0;i < 6*4*3;)
8570 for (j = 0;j < 3;j++, i++)
8571 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8573 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8576 void R_DrawLocs(void)
8579 cl_locnode_t *loc, *nearestloc;
8581 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8582 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8584 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8585 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8589 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8591 if (decalsystem->decals)
8592 Mem_Free(decalsystem->decals);
8593 memset(decalsystem, 0, sizeof(*decalsystem));
8596 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence)
8603 // expand or initialize the system
8604 if (decalsystem->maxdecals <= decalsystem->numdecals)
8606 decalsystem_t old = *decalsystem;
8607 qboolean useshortelements;
8608 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8609 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8610 decalsystem->decals = Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
8611 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8612 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8613 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8614 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8615 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8616 if (decalsystem->numdecals)
8617 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8619 Mem_Free(old.decals);
8620 for (i = 0;i < decalsystem->maxdecals*3;i++)
8621 decalsystem->element3i[i] = i;
8622 if (useshortelements)
8623 for (i = 0;i < decalsystem->maxdecals*3;i++)
8624 decalsystem->element3s[i] = i;
8627 // grab a decal and search for another free slot for the next one
8628 maxdecals = decalsystem->maxdecals;
8629 decals = decalsystem->decals;
8630 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8631 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8633 decalsystem->freedecal = i;
8634 if (decalsystem->numdecals <= i)
8635 decalsystem->numdecals = i + 1;
8637 // initialize the decal
8639 decal->triangleindex = triangleindex;
8640 decal->surfaceindex = surfaceindex;
8641 decal->decalsequence = decalsequence;
8642 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8643 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8644 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8645 decal->color4ub[0][3] = 255;
8646 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8647 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8648 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8649 decal->color4ub[1][3] = 255;
8650 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8651 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8652 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8653 decal->color4ub[2][3] = 255;
8654 decal->vertex3f[0][0] = v0[0];
8655 decal->vertex3f[0][1] = v0[1];
8656 decal->vertex3f[0][2] = v0[2];
8657 decal->vertex3f[1][0] = v1[0];
8658 decal->vertex3f[1][1] = v1[1];
8659 decal->vertex3f[1][2] = v1[2];
8660 decal->vertex3f[2][0] = v2[0];
8661 decal->vertex3f[2][1] = v2[1];
8662 decal->vertex3f[2][2] = v2[2];
8663 decal->texcoord2f[0][0] = t0[0];
8664 decal->texcoord2f[0][1] = t0[1];
8665 decal->texcoord2f[1][0] = t1[0];
8666 decal->texcoord2f[1][1] = t1[1];
8667 decal->texcoord2f[2][0] = t2[0];
8668 decal->texcoord2f[2][1] = t2[1];
8671 extern cvar_t cl_decals_bias;
8672 extern cvar_t cl_decals_models;
8673 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8674 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
8676 matrix4x4_t projection;
8677 decalsystem_t *decalsystem;
8679 qboolean notworld = ent != r_refdef.scene.worldentity;
8681 const float *vertex3f;
8682 const msurface_t *surface;
8683 const msurface_t *surfaces;
8684 const int *surfacelist;
8685 const texture_t *texture;
8689 int surfacelistindex;
8692 int decalsurfaceindex;
8697 float localorigin[3];
8698 float localnormal[3];
8709 float points[2][9][3];
8713 decalsystem = &ent->decalsystem;
8715 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8717 R_DecalSystem_Reset(&ent->decalsystem);
8721 if (!model->brush.data_nodes && !cl_decals_models.integer)
8723 if (decalsystem->model)
8724 R_DecalSystem_Reset(decalsystem);
8728 if (decalsystem->model != model)
8729 R_DecalSystem_Reset(decalsystem);
8730 decalsystem->model = model;
8732 RSurf_ActiveModelEntity(ent, false, false, false);
8734 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8735 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8736 VectorNormalize(localnormal);
8737 localsize = worldsize*rsurface.inversematrixscale;
8738 ilocalsize = 1.0f / localsize;
8739 localmins[0] = localorigin[0] - localsize;
8740 localmins[1] = localorigin[1] - localsize;
8741 localmins[2] = localorigin[2] - localsize;
8742 localmaxs[0] = localorigin[0] + localsize;
8743 localmaxs[1] = localorigin[1] + localsize;
8744 localmaxs[2] = localorigin[2] + localsize;
8746 //VectorCopy(localnormal, planes[4]);
8747 //VectorVectors(planes[4], planes[2], planes[0]);
8748 AnglesFromVectors(angles, localnormal, NULL, false);
8749 AngleVectors(angles, planes[0], planes[2], planes[4]);
8750 VectorNegate(planes[0], planes[1]);
8751 VectorNegate(planes[2], planes[3]);
8752 VectorNegate(planes[4], planes[5]);
8753 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8754 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8755 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8756 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8757 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8758 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8763 matrix4x4_t forwardprojection;
8764 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8765 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8770 float projectionvector[4][3];
8771 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8772 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8773 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8774 projectionvector[0][0] = planes[0][0] * ilocalsize;
8775 projectionvector[0][1] = planes[1][0] * ilocalsize;
8776 projectionvector[0][2] = planes[2][0] * ilocalsize;
8777 projectionvector[1][0] = planes[0][1] * ilocalsize;
8778 projectionvector[1][1] = planes[1][1] * ilocalsize;
8779 projectionvector[1][2] = planes[2][1] * ilocalsize;
8780 projectionvector[2][0] = planes[0][2] * ilocalsize;
8781 projectionvector[2][1] = planes[1][2] * ilocalsize;
8782 projectionvector[2][2] = planes[2][2] * ilocalsize;
8783 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8784 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8785 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8786 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8790 dynamic = model->surfmesh.isanimated;
8791 vertex3f = rsurface.modelvertex3f;
8792 numsurfacelist = model->nummodelsurfaces;
8793 surfacelist = model->sortedmodelsurfaces;
8794 surfaces = model->data_surfaces;
8795 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8797 surfaceindex = surfacelist[surfacelistindex];
8798 surface = surfaces + surfaceindex;
8799 // skip transparent surfaces
8800 texture = surface->texture;
8801 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8803 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8805 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8807 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8808 numvertices = surface->num_vertices;
8809 numtriangles = surface->num_triangles;
8810 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8812 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8814 index = 3*e[cornerindex];
8815 VectorCopy(vertex3f + index, v[cornerindex]);
8818 //TriangleNormal(v[0], v[1], v[2], normal);
8819 //if (DotProduct(normal, localnormal) < 0.0f)
8821 // clip by each of the box planes formed from the projection matrix
8822 // if anything survives, we emit the decal
8823 numpoints = PolygonF_Clip(3 , v[0] , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
8826 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
8829 numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
8832 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
8835 numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
8838 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
8841 // some part of the triangle survived, so we have to accept it...
8844 // dynamic always uses the original triangle
8846 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8848 index = 3*e[cornerindex];
8849 VectorCopy(vertex3f + index, v[cornerindex]);
8852 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8854 // convert vertex positions to texcoords
8855 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8856 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8857 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8858 // calculate distance fade from the projection origin
8859 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8860 f = bound(0.0f, f, 1.0f);
8861 c[cornerindex][0] = r * f;
8862 c[cornerindex][1] = g * f;
8863 c[cornerindex][2] = b * f;
8864 c[cornerindex][3] = 1.0f;
8865 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8868 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex+surface->num_firsttriangle, surfaceindex, decalsequence);
8870 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8871 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, notworld ? -1 : surfaceindex, decalsequence);
8876 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8877 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
8879 int renderentityindex;
8882 entity_render_t *ent;
8884 if (!cl_decals_newsystem.integer)
8887 worldmins[0] = worldorigin[0] - worldsize;
8888 worldmins[1] = worldorigin[1] - worldsize;
8889 worldmins[2] = worldorigin[2] - worldsize;
8890 worldmaxs[0] = worldorigin[0] + worldsize;
8891 worldmaxs[1] = worldorigin[1] + worldsize;
8892 worldmaxs[2] = worldorigin[2] + worldsize;
8894 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8896 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8898 ent = r_refdef.scene.entities[renderentityindex];
8899 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8902 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8906 typedef struct r_decalsystem_splatqueue_s
8915 r_decalsystem_splatqueue_t;
8917 int r_decalsystem_numqueued = 0;
8918 #define MAX_DECALSYSTEM_QUEUE 1024
8919 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8921 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
8923 r_decalsystem_splatqueue_t *queue;
8925 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8928 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8929 VectorCopy(worldorigin, queue->worldorigin);
8930 VectorCopy(worldnormal, queue->worldnormal);
8931 Vector4Set(queue->color, r, g, b, a);
8932 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8933 queue->worldsize = worldsize;
8934 queue->decalsequence = cl.decalsequence++;
8937 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8940 r_decalsystem_splatqueue_t *queue;
8942 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8943 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
8944 r_decalsystem_numqueued = 0;
8947 extern cvar_t cl_decals_max;
8948 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8951 decalsystem_t *decalsystem = &ent->decalsystem;
8958 if (!decalsystem->numdecals)
8961 if (r_showsurfaces.integer)
8964 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8966 R_DecalSystem_Reset(decalsystem);
8970 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8971 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8973 if (decalsystem->lastupdatetime)
8974 frametime = (cl.time - decalsystem->lastupdatetime);
8977 decalsystem->lastupdatetime = cl.time;
8978 decal = decalsystem->decals;
8979 numdecals = decalsystem->numdecals;
8981 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8983 if (decal->color4ub[0][3])
8985 decal->lived += frametime;
8986 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
8988 memset(decal, 0, sizeof(*decal));
8989 if (decalsystem->freedecal > i)
8990 decalsystem->freedecal = i;
8994 decal = decalsystem->decals;
8995 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
8998 // collapse the array by shuffling the tail decals into the gaps
9001 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
9002 decalsystem->freedecal++;
9003 if (decalsystem->freedecal == numdecals)
9005 decal[decalsystem->freedecal] = decal[--numdecals];
9008 decalsystem->numdecals = numdecals;
9012 // if there are no decals left, reset decalsystem
9013 R_DecalSystem_Reset(decalsystem);
9017 extern skinframe_t *decalskinframe;
9018 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9021 decalsystem_t *decalsystem = &ent->decalsystem;
9031 const unsigned char *surfacevisible = r_refdef.viewcache.world_surfacevisible;
9034 numdecals = decalsystem->numdecals;
9038 if (r_showsurfaces.integer)
9041 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9043 R_DecalSystem_Reset(decalsystem);
9047 // if the model is static it doesn't matter what value we give for
9048 // wantnormals and wanttangents, so this logic uses only rules applicable
9049 // to a model, knowing that they are meaningless otherwise
9050 if (ent == r_refdef.scene.worldentity)
9051 RSurf_ActiveWorldEntity();
9053 RSurf_ActiveModelEntity(ent, false, false, false);
9055 decalsystem->lastupdatetime = cl.time;
9056 decal = decalsystem->decals;
9058 fadedelay = cl_decals_time.value;
9059 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9061 // update vertex positions for animated models
9062 v3f = decalsystem->vertex3f;
9063 c4f = decalsystem->color4f;
9064 t2f = decalsystem->texcoord2f;
9065 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9067 if (!decal->color4ub[0][3])
9070 if (decal->surfaceindex >= 0 && !surfacevisible[decal->surfaceindex])
9073 // update color values for fading decals
9074 if (decal->lived >= cl_decals_time.value)
9076 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9077 alpha *= (1.0f/255.0f);
9080 alpha = 1.0f/255.0f;
9082 c4f[ 0] = decal->color4ub[0][0] * alpha;
9083 c4f[ 1] = decal->color4ub[0][1] * alpha;
9084 c4f[ 2] = decal->color4ub[0][2] * alpha;
9086 c4f[ 4] = decal->color4ub[1][0] * alpha;
9087 c4f[ 5] = decal->color4ub[1][1] * alpha;
9088 c4f[ 6] = decal->color4ub[1][2] * alpha;
9090 c4f[ 8] = decal->color4ub[2][0] * alpha;
9091 c4f[ 9] = decal->color4ub[2][1] * alpha;
9092 c4f[10] = decal->color4ub[2][2] * alpha;
9095 t2f[0] = decal->texcoord2f[0][0];
9096 t2f[1] = decal->texcoord2f[0][1];
9097 t2f[2] = decal->texcoord2f[1][0];
9098 t2f[3] = decal->texcoord2f[1][1];
9099 t2f[4] = decal->texcoord2f[2][0];
9100 t2f[5] = decal->texcoord2f[2][1];
9102 // update vertex positions for animated models
9103 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9105 e = rsurface.modelelement3i + 3*decal->triangleindex;
9106 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9107 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9108 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9112 VectorCopy(decal->vertex3f[0], v3f);
9113 VectorCopy(decal->vertex3f[1], v3f + 3);
9114 VectorCopy(decal->vertex3f[2], v3f + 6);
9125 r_refdef.stats.drawndecals += numtris;
9126 // now render the decals all at once
9127 // (this assumes they all use one particle font texture!)
9128 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
9129 R_Mesh_ResetTextureState();
9130 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9131 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9132 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9133 R_SetupGenericShader(true);
9134 GL_DepthMask(false);
9135 GL_DepthRange(0, 1);
9136 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9138 GL_CullFace(GL_NONE);
9139 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9140 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
9141 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
9142 GL_LockArrays(0, numtris * 3);
9143 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9144 GL_LockArrays(0, 0);
9148 static void R_DrawModelDecals(void)
9152 // fade faster when there are too many decals
9153 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9154 for (i = 0;i < r_refdef.scene.numentities;i++)
9155 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9157 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9158 for (i = 0;i < r_refdef.scene.numentities;i++)
9159 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9160 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9162 R_DecalSystem_ApplySplatEntitiesQueue();
9164 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9165 for (i = 0;i < r_refdef.scene.numentities;i++)
9166 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9168 r_refdef.stats.totaldecals += numdecals;
9170 if (r_showsurfaces.integer)
9173 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9175 for (i = 0;i < r_refdef.scene.numentities;i++)
9177 if (!r_refdef.viewcache.entityvisible[i])
9179 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9180 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9184 void R_DrawDebugModel(void)
9186 entity_render_t *ent = rsurface.entity;
9187 int i, j, k, l, flagsmask;
9188 const int *elements;
9190 const msurface_t *surface;
9191 dp_model_t *model = ent->model;
9194 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9196 R_Mesh_ColorPointer(NULL, 0, 0);
9197 R_Mesh_ResetTextureState();
9198 R_SetupGenericShader(false);
9199 GL_DepthRange(0, 1);
9200 GL_DepthTest(!r_showdisabledepthtest.integer);
9201 GL_DepthMask(false);
9202 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9204 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
9206 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9207 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
9209 if (brush->colbrushf && brush->colbrushf->numtriangles)
9211 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
9212 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);
9213 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
9216 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
9218 if (surface->num_collisiontriangles)
9220 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
9221 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);
9222 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
9227 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9229 if (r_showtris.integer || r_shownormals.integer)
9231 if (r_showdisabledepthtest.integer)
9233 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9234 GL_DepthMask(false);
9238 GL_BlendFunc(GL_ONE, GL_ZERO);
9241 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9243 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9245 rsurface.texture = R_GetCurrentTexture(surface->texture);
9246 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9248 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
9249 if (r_showtris.value > 0)
9251 if (!rsurface.texture->currentlayers->depthmask)
9252 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9253 else if (ent == r_refdef.scene.worldentity)
9254 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9256 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9257 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
9258 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
9259 R_Mesh_ColorPointer(NULL, 0, 0);
9260 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
9261 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9262 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
9263 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);
9264 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9267 if (r_shownormals.value < 0)
9270 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9272 VectorCopy(rsurface.vertex3f + l * 3, v);
9273 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9274 qglVertex3f(v[0], v[1], v[2]);
9275 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
9276 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9277 qglVertex3f(v[0], v[1], v[2]);
9282 if (r_shownormals.value > 0)
9285 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9287 VectorCopy(rsurface.vertex3f + l * 3, v);
9288 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9289 qglVertex3f(v[0], v[1], v[2]);
9290 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
9291 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9292 qglVertex3f(v[0], v[1], v[2]);
9297 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9299 VectorCopy(rsurface.vertex3f + l * 3, v);
9300 GL_Color(0, r_refdef.view.colorscale, 0, 1);
9301 qglVertex3f(v[0], v[1], v[2]);
9302 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
9303 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9304 qglVertex3f(v[0], v[1], v[2]);
9309 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9311 VectorCopy(rsurface.vertex3f + l * 3, v);
9312 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9313 qglVertex3f(v[0], v[1], v[2]);
9314 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
9315 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9316 qglVertex3f(v[0], v[1], v[2]);
9323 rsurface.texture = NULL;
9327 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
9328 int r_maxsurfacelist = 0;
9329 const msurface_t **r_surfacelist = NULL;
9330 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9332 int i, j, endj, f, flagsmask;
9334 dp_model_t *model = r_refdef.scene.worldmodel;
9335 msurface_t *surfaces;
9336 unsigned char *update;
9337 int numsurfacelist = 0;
9341 if (r_maxsurfacelist < model->num_surfaces)
9343 r_maxsurfacelist = model->num_surfaces;
9345 Mem_Free((msurface_t**)r_surfacelist);
9346 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9349 RSurf_ActiveWorldEntity();
9351 surfaces = model->data_surfaces;
9352 update = model->brushq1.lightmapupdateflags;
9354 // update light styles on this submodel
9355 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9357 model_brush_lightstyleinfo_t *style;
9358 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9360 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9362 int *list = style->surfacelist;
9363 style->value = r_refdef.scene.lightstylevalue[style->style];
9364 for (j = 0;j < style->numsurfaces;j++)
9365 update[list[j]] = true;
9370 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9375 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9381 rsurface.uselightmaptexture = false;
9382 rsurface.texture = NULL;
9383 rsurface.rtlight = NULL;
9385 // add visible surfaces to draw list
9386 for (i = 0;i < model->nummodelsurfaces;i++)
9388 j = model->sortedmodelsurfaces[i];
9389 if (r_refdef.viewcache.world_surfacevisible[j])
9390 r_surfacelist[numsurfacelist++] = surfaces + j;
9392 // update lightmaps if needed
9394 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9395 if (r_refdef.viewcache.world_surfacevisible[j])
9397 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9398 // don't do anything if there were no surfaces
9399 if (!numsurfacelist)
9401 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9404 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9405 GL_AlphaTest(false);
9407 // add to stats if desired
9408 if (r_speeds.integer && !skysurfaces && !depthonly)
9410 r_refdef.stats.world_surfaces += numsurfacelist;
9411 for (j = 0;j < numsurfacelist;j++)
9412 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9415 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9418 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9420 int i, j, endj, f, flagsmask;
9422 dp_model_t *model = ent->model;
9423 msurface_t *surfaces;
9424 unsigned char *update;
9425 int numsurfacelist = 0;
9429 if (r_maxsurfacelist < model->num_surfaces)
9431 r_maxsurfacelist = model->num_surfaces;
9433 Mem_Free((msurface_t **)r_surfacelist);
9434 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9437 // if the model is static it doesn't matter what value we give for
9438 // wantnormals and wanttangents, so this logic uses only rules applicable
9439 // to a model, knowing that they are meaningless otherwise
9440 if (ent == r_refdef.scene.worldentity)
9441 RSurf_ActiveWorldEntity();
9442 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9443 RSurf_ActiveModelEntity(ent, false, false, false);
9445 RSurf_ActiveModelEntity(ent, true, true, true);
9447 RSurf_ActiveModelEntity(ent, false, false, false);
9450 switch (vid.renderpath)
9452 case RENDERPATH_GL20:
9453 RSurf_ActiveModelEntity(ent, true, true, false);
9455 case RENDERPATH_GL13:
9456 case RENDERPATH_GL11:
9457 RSurf_ActiveModelEntity(ent, true, false, false);
9462 surfaces = model->data_surfaces;
9463 update = model->brushq1.lightmapupdateflags;
9465 // update light styles
9466 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9468 model_brush_lightstyleinfo_t *style;
9469 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9471 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9473 int *list = style->surfacelist;
9474 style->value = r_refdef.scene.lightstylevalue[style->style];
9475 for (j = 0;j < style->numsurfaces;j++)
9476 update[list[j]] = true;
9481 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9486 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9492 rsurface.uselightmaptexture = false;
9493 rsurface.texture = NULL;
9494 rsurface.rtlight = NULL;
9496 // add visible surfaces to draw list
9497 for (i = 0;i < model->nummodelsurfaces;i++)
9498 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9499 // don't do anything if there were no surfaces
9500 if (!numsurfacelist)
9502 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9505 // update lightmaps if needed
9507 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9509 R_BuildLightMap(ent, surfaces + j);
9510 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9511 GL_AlphaTest(false);
9513 // add to stats if desired
9514 if (r_speeds.integer && !skysurfaces && !depthonly)
9516 r_refdef.stats.entities_surfaces += numsurfacelist;
9517 for (j = 0;j < numsurfacelist;j++)
9518 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9521 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9524 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
9526 static texture_t texture;
9527 static msurface_t surface;
9528 const msurface_t *surfacelist = &surface;
9530 // fake enough texture and surface state to render this geometry
9532 texture.update_lastrenderframe = -1; // regenerate this texture
9533 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9534 texture.currentskinframe = skinframe;
9535 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9536 texture.specularscalemod = 1;
9537 texture.specularpowermod = 1;
9539 surface.texture = &texture;
9540 surface.num_triangles = numtriangles;
9541 surface.num_firsttriangle = firsttriangle;
9542 surface.num_vertices = numvertices;
9543 surface.num_firstvertex = firstvertex;
9546 rsurface.texture = R_GetCurrentTexture(surface.texture);
9547 rsurface.uselightmaptexture = false;
9548 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);