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 && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
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)
6152 int blendfunc1, blendfunc2;
6154 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6156 blendfunc1 = GL_SRC_ALPHA;
6157 blendfunc2 = GL_ONE;
6159 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6161 blendfunc1 = GL_SRC_ALPHA;
6162 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6164 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6166 blendfunc1 = t->customblendfunc[0];
6167 blendfunc2 = t->customblendfunc[1];
6171 blendfunc1 = GL_ONE;
6172 blendfunc2 = GL_ZERO;
6174 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
6175 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6177 // fullbright is not affected by r_refdef.lightmapintensity
6178 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]);
6179 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6180 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]);
6181 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6182 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]);
6186 vec3_t ambientcolor;
6188 // set the color tint used for lights affecting this surface
6189 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
6191 // q3bsp has no lightmap updates, so the lightstylevalue that
6192 // would normally be baked into the lightmap must be
6193 // applied to the color
6194 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
6195 if (model->type == mod_brushq3)
6196 colorscale *= r_refdef.scene.rtlightstylevalue[0];
6197 colorscale *= r_refdef.lightmapintensity;
6198 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
6199 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
6200 // basic lit geometry
6201 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]);
6202 // add pants/shirt if needed
6203 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6204 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]);
6205 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6206 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]);
6207 // now add ambient passes if needed
6208 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
6210 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]);
6211 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6212 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]);
6213 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6214 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]);
6217 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
6218 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]);
6219 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
6221 // if this is opaque use alpha blend which will darken the earlier
6224 // if this is an alpha blended material, all the earlier passes
6225 // were darkened by fog already, so we only need to add the fog
6226 // color ontop through the fog mask texture
6228 // if this is an additive blended material, all the earlier passes
6229 // were darkened by fog already, and we should not add fog color
6230 // (because the background was not darkened, there is no fog color
6231 // that was lost behind it).
6232 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]);
6236 return t->currentframe;
6239 rsurfacestate_t rsurface;
6241 void R_Mesh_ResizeArrays(int newvertices)
6244 if (rsurface.array_size >= newvertices)
6246 if (rsurface.array_modelvertex3f)
6247 Mem_Free(rsurface.array_modelvertex3f);
6248 rsurface.array_size = (newvertices + 1023) & ~1023;
6249 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6250 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
6251 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
6252 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
6253 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
6254 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
6255 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6256 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6257 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
6258 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
6259 rsurface.array_color4f = base + rsurface.array_size * 27;
6260 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6263 void RSurf_ActiveWorldEntity(void)
6265 dp_model_t *model = r_refdef.scene.worldmodel;
6266 //if (rsurface.entity == r_refdef.scene.worldentity)
6268 rsurface.entity = r_refdef.scene.worldentity;
6269 rsurface.skeleton = NULL;
6270 rsurface.ent_skinnum = 0;
6271 rsurface.ent_qwskin = -1;
6272 rsurface.ent_shadertime = 0;
6273 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6274 if (rsurface.array_size < model->surfmesh.num_vertices)
6275 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6276 rsurface.matrix = identitymatrix;
6277 rsurface.inversematrix = identitymatrix;
6278 rsurface.matrixscale = 1;
6279 rsurface.inversematrixscale = 1;
6280 R_Mesh_Matrix(&identitymatrix);
6281 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6282 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6283 rsurface.fograngerecip = r_refdef.fograngerecip;
6284 rsurface.fogheightfade = r_refdef.fogheightfade;
6285 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6286 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6287 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6288 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6289 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6290 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6291 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6292 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
6293 rsurface.colormod[3] = 1;
6294 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);
6295 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6296 rsurface.frameblend[0].lerp = 1;
6297 rsurface.ent_alttextures = false;
6298 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6299 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6300 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6301 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6302 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6303 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6304 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6305 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6306 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6307 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6308 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6309 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6310 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6311 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6312 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6313 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6314 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6315 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6316 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6317 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6318 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6319 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6320 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6321 rsurface.modelelement3i = model->surfmesh.data_element3i;
6322 rsurface.modelelement3s = model->surfmesh.data_element3s;
6323 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6324 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6325 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6326 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6327 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6328 rsurface.modelsurfaces = model->data_surfaces;
6329 rsurface.generatedvertex = false;
6330 rsurface.vertex3f = rsurface.modelvertex3f;
6331 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6332 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6333 rsurface.svector3f = rsurface.modelsvector3f;
6334 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6335 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6336 rsurface.tvector3f = rsurface.modeltvector3f;
6337 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6338 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6339 rsurface.normal3f = rsurface.modelnormal3f;
6340 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6341 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6342 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6345 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
6347 dp_model_t *model = ent->model;
6348 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6350 rsurface.entity = (entity_render_t *)ent;
6351 rsurface.skeleton = ent->skeleton;
6352 rsurface.ent_skinnum = ent->skinnum;
6353 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;
6354 rsurface.ent_shadertime = ent->shadertime;
6355 rsurface.ent_flags = ent->flags;
6356 if (rsurface.array_size < model->surfmesh.num_vertices)
6357 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6358 rsurface.matrix = ent->matrix;
6359 rsurface.inversematrix = ent->inversematrix;
6360 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6361 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6362 R_Mesh_Matrix(&rsurface.matrix);
6363 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6364 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6365 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6366 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6367 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6368 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6369 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6370 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6371 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6372 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6373 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6374 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
6375 rsurface.colormod[3] = ent->alpha;
6376 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
6377 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6378 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6379 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6380 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6381 if (ent->model->brush.submodel && !prepass)
6383 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6384 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6386 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6388 if (ent->animcache_vertex3f && !r_framedata_failed)
6390 rsurface.modelvertex3f = ent->animcache_vertex3f;
6391 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
6392 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
6393 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
6395 else if (wanttangents)
6397 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6398 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6399 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6400 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6401 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6403 else if (wantnormals)
6405 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6406 rsurface.modelsvector3f = NULL;
6407 rsurface.modeltvector3f = NULL;
6408 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6409 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6413 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6414 rsurface.modelsvector3f = NULL;
6415 rsurface.modeltvector3f = NULL;
6416 rsurface.modelnormal3f = NULL;
6417 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6419 rsurface.modelvertex3f_bufferobject = 0;
6420 rsurface.modelvertex3f_bufferoffset = 0;
6421 rsurface.modelsvector3f_bufferobject = 0;
6422 rsurface.modelsvector3f_bufferoffset = 0;
6423 rsurface.modeltvector3f_bufferobject = 0;
6424 rsurface.modeltvector3f_bufferoffset = 0;
6425 rsurface.modelnormal3f_bufferobject = 0;
6426 rsurface.modelnormal3f_bufferoffset = 0;
6427 rsurface.generatedvertex = true;
6431 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6432 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6433 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6434 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6435 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6436 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6437 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6438 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6439 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6440 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6441 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6442 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6443 rsurface.generatedvertex = false;
6445 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6446 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6447 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6448 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6449 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6450 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6451 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6452 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6453 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6454 rsurface.modelelement3i = model->surfmesh.data_element3i;
6455 rsurface.modelelement3s = model->surfmesh.data_element3s;
6456 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6457 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6458 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6459 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6460 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6461 rsurface.modelsurfaces = model->data_surfaces;
6462 rsurface.vertex3f = rsurface.modelvertex3f;
6463 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6464 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6465 rsurface.svector3f = rsurface.modelsvector3f;
6466 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6467 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6468 rsurface.tvector3f = rsurface.modeltvector3f;
6469 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6470 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6471 rsurface.normal3f = rsurface.modelnormal3f;
6472 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6473 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6474 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6477 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)
6479 rsurface.entity = r_refdef.scene.worldentity;
6480 rsurface.skeleton = NULL;
6481 rsurface.ent_skinnum = 0;
6482 rsurface.ent_qwskin = -1;
6483 rsurface.ent_shadertime = shadertime;
6484 rsurface.ent_flags = entflags;
6485 rsurface.modelnum_vertices = numvertices;
6486 rsurface.modelnum_triangles = numtriangles;
6487 if (rsurface.array_size < rsurface.modelnum_vertices)
6488 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6489 rsurface.matrix = *matrix;
6490 rsurface.inversematrix = *inversematrix;
6491 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6492 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6493 R_Mesh_Matrix(&rsurface.matrix);
6494 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6495 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6496 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6497 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6498 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6499 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6500 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6501 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6502 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6503 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6504 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6505 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
6506 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);
6507 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6508 rsurface.frameblend[0].lerp = 1;
6509 rsurface.ent_alttextures = false;
6510 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6511 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6514 rsurface.modelvertex3f = vertex3f;
6515 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6516 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6517 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6519 else if (wantnormals)
6521 rsurface.modelvertex3f = vertex3f;
6522 rsurface.modelsvector3f = NULL;
6523 rsurface.modeltvector3f = NULL;
6524 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6528 rsurface.modelvertex3f = vertex3f;
6529 rsurface.modelsvector3f = NULL;
6530 rsurface.modeltvector3f = NULL;
6531 rsurface.modelnormal3f = NULL;
6533 rsurface.modelvertex3f_bufferobject = 0;
6534 rsurface.modelvertex3f_bufferoffset = 0;
6535 rsurface.modelsvector3f_bufferobject = 0;
6536 rsurface.modelsvector3f_bufferoffset = 0;
6537 rsurface.modeltvector3f_bufferobject = 0;
6538 rsurface.modeltvector3f_bufferoffset = 0;
6539 rsurface.modelnormal3f_bufferobject = 0;
6540 rsurface.modelnormal3f_bufferoffset = 0;
6541 rsurface.generatedvertex = true;
6542 rsurface.modellightmapcolor4f = color4f;
6543 rsurface.modellightmapcolor4f_bufferobject = 0;
6544 rsurface.modellightmapcolor4f_bufferoffset = 0;
6545 rsurface.modeltexcoordtexture2f = texcoord2f;
6546 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6547 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6548 rsurface.modeltexcoordlightmap2f = NULL;
6549 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6550 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6551 rsurface.modelelement3i = element3i;
6552 rsurface.modelelement3s = element3s;
6553 rsurface.modelelement3i_bufferobject = 0;
6554 rsurface.modelelement3s_bufferobject = 0;
6555 rsurface.modellightmapoffsets = NULL;
6556 rsurface.modelsurfaces = NULL;
6557 rsurface.vertex3f = rsurface.modelvertex3f;
6558 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6559 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6560 rsurface.svector3f = rsurface.modelsvector3f;
6561 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6562 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6563 rsurface.tvector3f = rsurface.modeltvector3f;
6564 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6565 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6566 rsurface.normal3f = rsurface.modelnormal3f;
6567 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6568 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6569 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6571 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6573 if ((wantnormals || wanttangents) && !normal3f)
6574 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6575 if (wanttangents && !svector3f)
6576 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);
6580 float RSurf_FogPoint(const float *v)
6582 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6583 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6584 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6585 float FogHeightFade = r_refdef.fogheightfade;
6587 unsigned int fogmasktableindex;
6588 if (r_refdef.fogplaneviewabove)
6589 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6591 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6592 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6593 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6596 float RSurf_FogVertex(const float *v)
6598 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6599 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6600 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6601 float FogHeightFade = rsurface.fogheightfade;
6603 unsigned int fogmasktableindex;
6604 if (r_refdef.fogplaneviewabove)
6605 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6607 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6608 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6609 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6612 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6613 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6616 int texturesurfaceindex;
6621 const float *v1, *in_tc;
6623 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6625 q3shaderinfo_deform_t *deform;
6626 // 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
6627 if (rsurface.generatedvertex)
6629 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6630 generatenormals = true;
6631 for (i = 0;i < Q3MAXDEFORMS;i++)
6633 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6635 generatetangents = true;
6636 generatenormals = true;
6638 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6639 generatenormals = true;
6641 if (generatenormals && !rsurface.modelnormal3f)
6643 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6644 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6645 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6646 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6648 if (generatetangents && !rsurface.modelsvector3f)
6650 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6651 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6652 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6653 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6654 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6655 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6656 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);
6659 rsurface.vertex3f = rsurface.modelvertex3f;
6660 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6661 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6662 rsurface.svector3f = rsurface.modelsvector3f;
6663 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6664 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6665 rsurface.tvector3f = rsurface.modeltvector3f;
6666 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6667 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6668 rsurface.normal3f = rsurface.modelnormal3f;
6669 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6670 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6671 // if vertices are deformed (sprite flares and things in maps, possibly
6672 // water waves, bulges and other deformations), generate them into
6673 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6674 // (may be static model data or generated data for an animated model, or
6675 // the previous deform pass)
6676 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6678 switch (deform->deform)
6681 case Q3DEFORM_PROJECTIONSHADOW:
6682 case Q3DEFORM_TEXT0:
6683 case Q3DEFORM_TEXT1:
6684 case Q3DEFORM_TEXT2:
6685 case Q3DEFORM_TEXT3:
6686 case Q3DEFORM_TEXT4:
6687 case Q3DEFORM_TEXT5:
6688 case Q3DEFORM_TEXT6:
6689 case Q3DEFORM_TEXT7:
6692 case Q3DEFORM_AUTOSPRITE:
6693 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6694 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6695 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6696 VectorNormalize(newforward);
6697 VectorNormalize(newright);
6698 VectorNormalize(newup);
6699 // make deformed versions of only the model vertices used by the specified surfaces
6700 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6702 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6703 // a single autosprite surface can contain multiple sprites...
6704 for (j = 0;j < surface->num_vertices - 3;j += 4)
6706 VectorClear(center);
6707 for (i = 0;i < 4;i++)
6708 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6709 VectorScale(center, 0.25f, center);
6710 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6711 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6712 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6713 for (i = 0;i < 4;i++)
6715 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6716 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6719 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);
6720 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);
6722 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6723 rsurface.vertex3f_bufferobject = 0;
6724 rsurface.vertex3f_bufferoffset = 0;
6725 rsurface.svector3f = rsurface.array_deformedsvector3f;
6726 rsurface.svector3f_bufferobject = 0;
6727 rsurface.svector3f_bufferoffset = 0;
6728 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6729 rsurface.tvector3f_bufferobject = 0;
6730 rsurface.tvector3f_bufferoffset = 0;
6731 rsurface.normal3f = rsurface.array_deformednormal3f;
6732 rsurface.normal3f_bufferobject = 0;
6733 rsurface.normal3f_bufferoffset = 0;
6735 case Q3DEFORM_AUTOSPRITE2:
6736 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6737 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6738 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6739 VectorNormalize(newforward);
6740 VectorNormalize(newright);
6741 VectorNormalize(newup);
6742 // make deformed versions of only the model vertices used by the specified surfaces
6743 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6745 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6746 const float *v1, *v2;
6756 memset(shortest, 0, sizeof(shortest));
6757 // a single autosprite surface can contain multiple sprites...
6758 for (j = 0;j < surface->num_vertices - 3;j += 4)
6760 VectorClear(center);
6761 for (i = 0;i < 4;i++)
6762 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6763 VectorScale(center, 0.25f, center);
6764 // find the two shortest edges, then use them to define the
6765 // axis vectors for rotating around the central axis
6766 for (i = 0;i < 6;i++)
6768 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6769 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6771 Debug_PolygonBegin(NULL, 0);
6772 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6773 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);
6774 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6777 l = VectorDistance2(v1, v2);
6778 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6780 l += (1.0f / 1024.0f);
6781 if (shortest[0].length2 > l || i == 0)
6783 shortest[1] = shortest[0];
6784 shortest[0].length2 = l;
6785 shortest[0].v1 = v1;
6786 shortest[0].v2 = v2;
6788 else if (shortest[1].length2 > l || i == 1)
6790 shortest[1].length2 = l;
6791 shortest[1].v1 = v1;
6792 shortest[1].v2 = v2;
6795 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6796 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6798 Debug_PolygonBegin(NULL, 0);
6799 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6800 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);
6801 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6804 // this calculates the right vector from the shortest edge
6805 // and the up vector from the edge midpoints
6806 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6807 VectorNormalize(right);
6808 VectorSubtract(end, start, up);
6809 VectorNormalize(up);
6810 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6811 VectorSubtract(rsurface.localvieworigin, center, forward);
6812 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6813 VectorNegate(forward, forward);
6814 VectorReflect(forward, 0, up, forward);
6815 VectorNormalize(forward);
6816 CrossProduct(up, forward, newright);
6817 VectorNormalize(newright);
6819 Debug_PolygonBegin(NULL, 0);
6820 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);
6821 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6822 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6826 Debug_PolygonBegin(NULL, 0);
6827 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6828 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6829 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6832 // rotate the quad around the up axis vector, this is made
6833 // especially easy by the fact we know the quad is flat,
6834 // so we only have to subtract the center position and
6835 // measure distance along the right vector, and then
6836 // multiply that by the newright vector and add back the
6838 // we also need to subtract the old position to undo the
6839 // displacement from the center, which we do with a
6840 // DotProduct, the subtraction/addition of center is also
6841 // optimized into DotProducts here
6842 l = DotProduct(right, center);
6843 for (i = 0;i < 4;i++)
6845 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6846 f = DotProduct(right, v1) - l;
6847 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6850 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);
6851 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);
6853 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6854 rsurface.vertex3f_bufferobject = 0;
6855 rsurface.vertex3f_bufferoffset = 0;
6856 rsurface.svector3f = rsurface.array_deformedsvector3f;
6857 rsurface.svector3f_bufferobject = 0;
6858 rsurface.svector3f_bufferoffset = 0;
6859 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6860 rsurface.tvector3f_bufferobject = 0;
6861 rsurface.tvector3f_bufferoffset = 0;
6862 rsurface.normal3f = rsurface.array_deformednormal3f;
6863 rsurface.normal3f_bufferobject = 0;
6864 rsurface.normal3f_bufferoffset = 0;
6866 case Q3DEFORM_NORMAL:
6867 // deform the normals to make reflections wavey
6868 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6870 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6871 for (j = 0;j < surface->num_vertices;j++)
6874 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6875 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6876 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6877 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6878 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6879 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6880 VectorNormalize(normal);
6882 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);
6884 rsurface.svector3f = rsurface.array_deformedsvector3f;
6885 rsurface.svector3f_bufferobject = 0;
6886 rsurface.svector3f_bufferoffset = 0;
6887 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6888 rsurface.tvector3f_bufferobject = 0;
6889 rsurface.tvector3f_bufferoffset = 0;
6890 rsurface.normal3f = rsurface.array_deformednormal3f;
6891 rsurface.normal3f_bufferobject = 0;
6892 rsurface.normal3f_bufferoffset = 0;
6895 // deform vertex array to make wavey water and flags and such
6896 waveparms[0] = deform->waveparms[0];
6897 waveparms[1] = deform->waveparms[1];
6898 waveparms[2] = deform->waveparms[2];
6899 waveparms[3] = deform->waveparms[3];
6900 // this is how a divisor of vertex influence on deformation
6901 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6902 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6903 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6905 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6906 for (j = 0;j < surface->num_vertices;j++)
6908 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6909 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6910 // if the wavefunc depends on time, evaluate it per-vertex
6913 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6914 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6916 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6919 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6920 rsurface.vertex3f_bufferobject = 0;
6921 rsurface.vertex3f_bufferoffset = 0;
6923 case Q3DEFORM_BULGE:
6924 // deform vertex array to make the surface have moving bulges
6925 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6927 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6928 for (j = 0;j < surface->num_vertices;j++)
6930 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6931 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6934 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6935 rsurface.vertex3f_bufferobject = 0;
6936 rsurface.vertex3f_bufferoffset = 0;
6939 // deform vertex array
6940 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6941 VectorScale(deform->parms, scale, waveparms);
6942 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6944 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6945 for (j = 0;j < surface->num_vertices;j++)
6946 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6948 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6949 rsurface.vertex3f_bufferobject = 0;
6950 rsurface.vertex3f_bufferoffset = 0;
6954 // generate texcoords based on the chosen texcoord source
6955 switch(rsurface.texture->tcgen.tcgen)
6958 case Q3TCGEN_TEXTURE:
6959 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6960 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6961 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6963 case Q3TCGEN_LIGHTMAP:
6964 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6965 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6966 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6968 case Q3TCGEN_VECTOR:
6969 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6971 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6972 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)
6974 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6975 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6978 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6979 rsurface.texcoordtexture2f_bufferobject = 0;
6980 rsurface.texcoordtexture2f_bufferoffset = 0;
6982 case Q3TCGEN_ENVIRONMENT:
6983 // make environment reflections using a spheremap
6984 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6986 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6987 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6988 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6989 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6990 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6992 // identical to Q3A's method, but executed in worldspace so
6993 // carried models can be shiny too
6995 float viewer[3], d, reflected[3], worldreflected[3];
6997 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6998 // VectorNormalize(viewer);
7000 d = DotProduct(normal, viewer);
7002 reflected[0] = normal[0]*2*d - viewer[0];
7003 reflected[1] = normal[1]*2*d - viewer[1];
7004 reflected[2] = normal[2]*2*d - viewer[2];
7005 // note: this is proportinal to viewer, so we can normalize later
7007 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7008 VectorNormalize(worldreflected);
7010 // note: this sphere map only uses world x and z!
7011 // so positive and negative y will LOOK THE SAME.
7012 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7013 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7016 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7017 rsurface.texcoordtexture2f_bufferobject = 0;
7018 rsurface.texcoordtexture2f_bufferoffset = 0;
7021 // the only tcmod that needs software vertex processing is turbulent, so
7022 // check for it here and apply the changes if needed
7023 // and we only support that as the first one
7024 // (handling a mixture of turbulent and other tcmods would be problematic
7025 // without punting it entirely to a software path)
7026 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7028 amplitude = rsurface.texture->tcmods[0].parms[1];
7029 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7030 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7032 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7033 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)
7035 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7036 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7039 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7040 rsurface.texcoordtexture2f_bufferobject = 0;
7041 rsurface.texcoordtexture2f_bufferoffset = 0;
7043 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7044 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7045 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7046 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7049 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7052 const msurface_t *surface = texturesurfacelist[0];
7053 const msurface_t *surface2;
7058 // TODO: lock all array ranges before render, rather than on each surface
7059 if (texturenumsurfaces == 1)
7061 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7062 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);
7064 else if (r_batchmode.integer == 2)
7066 #define MAXBATCHTRIANGLES 4096
7067 int batchtriangles = 0;
7068 int batchelements[MAXBATCHTRIANGLES*3];
7069 for (i = 0;i < texturenumsurfaces;i = j)
7071 surface = texturesurfacelist[i];
7073 if (surface->num_triangles > MAXBATCHTRIANGLES)
7075 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);
7078 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7079 batchtriangles = surface->num_triangles;
7080 firstvertex = surface->num_firstvertex;
7081 endvertex = surface->num_firstvertex + surface->num_vertices;
7082 for (;j < texturenumsurfaces;j++)
7084 surface2 = texturesurfacelist[j];
7085 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7087 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7088 batchtriangles += surface2->num_triangles;
7089 firstvertex = min(firstvertex, surface2->num_firstvertex);
7090 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7092 surface2 = texturesurfacelist[j-1];
7093 numvertices = endvertex - firstvertex;
7094 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7097 else if (r_batchmode.integer == 1)
7099 for (i = 0;i < texturenumsurfaces;i = j)
7101 surface = texturesurfacelist[i];
7102 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7103 if (texturesurfacelist[j] != surface2)
7105 surface2 = texturesurfacelist[j-1];
7106 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7107 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7108 GL_LockArrays(surface->num_firstvertex, numvertices);
7109 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7114 for (i = 0;i < texturenumsurfaces;i++)
7116 surface = texturesurfacelist[i];
7117 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7118 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);
7123 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
7125 int i, planeindex, vertexindex;
7129 r_waterstate_waterplane_t *p, *bestp;
7130 const msurface_t *surface;
7131 if (r_waterstate.renderingscene)
7133 for (i = 0;i < texturenumsurfaces;i++)
7135 surface = texturesurfacelist[i];
7136 if (lightmaptexunit >= 0)
7137 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7138 if (deluxemaptexunit >= 0)
7139 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7140 // pick the closest matching water plane
7143 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7146 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7148 Matrix4x4_Transform(&rsurface.matrix, v, vert);
7149 d += fabs(PlaneDiff(vert, &p->plane));
7151 if (bestd > d || !bestp)
7159 if (refractiontexunit >= 0)
7160 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
7161 if (reflectiontexunit >= 0)
7162 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
7166 if (refractiontexunit >= 0)
7167 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
7168 if (reflectiontexunit >= 0)
7169 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
7171 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7172 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);
7176 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
7180 const msurface_t *surface = texturesurfacelist[0];
7181 const msurface_t *surface2;
7186 // TODO: lock all array ranges before render, rather than on each surface
7187 if (texturenumsurfaces == 1)
7189 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7190 if (deluxemaptexunit >= 0)
7191 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7192 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7193 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);
7195 else if (r_batchmode.integer == 2)
7197 #define MAXBATCHTRIANGLES 4096
7198 int batchtriangles = 0;
7199 int batchelements[MAXBATCHTRIANGLES*3];
7200 for (i = 0;i < texturenumsurfaces;i = j)
7202 surface = texturesurfacelist[i];
7203 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7204 if (deluxemaptexunit >= 0)
7205 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7207 if (surface->num_triangles > MAXBATCHTRIANGLES)
7209 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);
7212 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7213 batchtriangles = surface->num_triangles;
7214 firstvertex = surface->num_firstvertex;
7215 endvertex = surface->num_firstvertex + surface->num_vertices;
7216 for (;j < texturenumsurfaces;j++)
7218 surface2 = texturesurfacelist[j];
7219 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7221 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7222 batchtriangles += surface2->num_triangles;
7223 firstvertex = min(firstvertex, surface2->num_firstvertex);
7224 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7226 surface2 = texturesurfacelist[j-1];
7227 numvertices = endvertex - firstvertex;
7228 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7231 else if (r_batchmode.integer == 1)
7234 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
7235 for (i = 0;i < texturenumsurfaces;i = j)
7237 surface = texturesurfacelist[i];
7238 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7239 if (texturesurfacelist[j] != surface2)
7241 Con_Printf(" %i", j - i);
7244 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
7246 for (i = 0;i < texturenumsurfaces;i = j)
7248 surface = texturesurfacelist[i];
7249 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7250 if (deluxemaptexunit >= 0)
7251 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7252 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7253 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7256 Con_Printf(" %i", j - i);
7258 surface2 = texturesurfacelist[j-1];
7259 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7260 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7261 GL_LockArrays(surface->num_firstvertex, numvertices);
7262 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7270 for (i = 0;i < texturenumsurfaces;i++)
7272 surface = texturesurfacelist[i];
7273 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7274 if (deluxemaptexunit >= 0)
7275 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7276 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7277 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);
7282 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7285 int texturesurfaceindex;
7286 if (r_showsurfaces.integer == 2)
7288 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7290 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7291 for (j = 0;j < surface->num_triangles;j++)
7293 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7294 GL_Color(f, f, f, 1);
7295 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7301 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7303 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7304 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7305 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);
7306 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7307 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);
7312 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7314 int texturesurfaceindex;
7318 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7320 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7321 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)
7329 rsurface.lightmapcolor4f = rsurface.array_color4f;
7330 rsurface.lightmapcolor4f_bufferobject = 0;
7331 rsurface.lightmapcolor4f_bufferoffset = 0;
7334 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7336 int texturesurfaceindex;
7342 if (rsurface.lightmapcolor4f)
7344 // generate color arrays for the surfaces in this list
7345 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7347 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7348 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)
7350 f = RSurf_FogVertex(v);
7360 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7362 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7363 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)
7365 f = RSurf_FogVertex(v);
7373 rsurface.lightmapcolor4f = rsurface.array_color4f;
7374 rsurface.lightmapcolor4f_bufferobject = 0;
7375 rsurface.lightmapcolor4f_bufferoffset = 0;
7378 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7380 int texturesurfaceindex;
7386 if (!rsurface.lightmapcolor4f)
7388 // generate color arrays for the surfaces in this list
7389 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7391 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7392 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)
7394 f = RSurf_FogVertex(v);
7395 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7396 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7397 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7401 rsurface.lightmapcolor4f = rsurface.array_color4f;
7402 rsurface.lightmapcolor4f_bufferobject = 0;
7403 rsurface.lightmapcolor4f_bufferoffset = 0;
7406 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7408 int texturesurfaceindex;
7412 if (!rsurface.lightmapcolor4f)
7414 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7416 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7417 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)
7425 rsurface.lightmapcolor4f = rsurface.array_color4f;
7426 rsurface.lightmapcolor4f_bufferobject = 0;
7427 rsurface.lightmapcolor4f_bufferoffset = 0;
7430 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7432 int texturesurfaceindex;
7436 if (!rsurface.lightmapcolor4f)
7438 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7440 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7441 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)
7443 c2[0] = c[0] + r_refdef.scene.ambient;
7444 c2[1] = c[1] + r_refdef.scene.ambient;
7445 c2[2] = c[2] + r_refdef.scene.ambient;
7449 rsurface.lightmapcolor4f = rsurface.array_color4f;
7450 rsurface.lightmapcolor4f_bufferobject = 0;
7451 rsurface.lightmapcolor4f_bufferoffset = 0;
7454 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7457 rsurface.lightmapcolor4f = NULL;
7458 rsurface.lightmapcolor4f_bufferobject = 0;
7459 rsurface.lightmapcolor4f_bufferoffset = 0;
7460 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7461 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7462 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7463 GL_Color(r, g, b, a);
7464 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7467 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7469 // TODO: optimize applyfog && applycolor case
7470 // just apply fog if necessary, and tint the fog color array if necessary
7471 rsurface.lightmapcolor4f = NULL;
7472 rsurface.lightmapcolor4f_bufferobject = 0;
7473 rsurface.lightmapcolor4f_bufferoffset = 0;
7474 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7475 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7476 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7477 GL_Color(r, g, b, a);
7478 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7481 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7483 int texturesurfaceindex;
7487 if (texturesurfacelist[0]->lightmapinfo)
7489 // generate color arrays for the surfaces in this list
7490 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7492 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7493 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7495 if (surface->lightmapinfo->samples)
7497 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7498 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7499 VectorScale(lm, scale, c);
7500 if (surface->lightmapinfo->styles[1] != 255)
7502 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7504 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7505 VectorMA(c, scale, lm, c);
7506 if (surface->lightmapinfo->styles[2] != 255)
7509 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7510 VectorMA(c, scale, lm, c);
7511 if (surface->lightmapinfo->styles[3] != 255)
7514 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7515 VectorMA(c, scale, lm, c);
7525 rsurface.lightmapcolor4f = rsurface.array_color4f;
7526 rsurface.lightmapcolor4f_bufferobject = 0;
7527 rsurface.lightmapcolor4f_bufferoffset = 0;
7531 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7532 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7533 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7535 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7536 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7537 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7538 GL_Color(r, g, b, a);
7539 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7542 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7544 int texturesurfaceindex;
7551 vec3_t ambientcolor;
7552 vec3_t diffusecolor;
7556 VectorCopy(rsurface.modellight_lightdir, lightdir);
7557 f = 0.5f * r_refdef.lightmapintensity;
7558 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7559 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7560 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7561 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7562 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7563 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7565 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7567 // generate color arrays for the surfaces in this list
7568 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7570 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7571 int numverts = surface->num_vertices;
7572 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7573 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7574 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7575 // q3-style directional shading
7576 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7578 if ((f = DotProduct(n, lightdir)) > 0)
7579 VectorMA(ambientcolor, f, diffusecolor, c);
7581 VectorCopy(ambientcolor, c);
7589 rsurface.lightmapcolor4f = rsurface.array_color4f;
7590 rsurface.lightmapcolor4f_bufferobject = 0;
7591 rsurface.lightmapcolor4f_bufferoffset = 0;
7592 *applycolor = false;
7596 *r = ambientcolor[0];
7597 *g = ambientcolor[1];
7598 *b = ambientcolor[2];
7599 rsurface.lightmapcolor4f = NULL;
7600 rsurface.lightmapcolor4f_bufferobject = 0;
7601 rsurface.lightmapcolor4f_bufferoffset = 0;
7605 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7607 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7608 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7609 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7610 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7611 GL_Color(r, g, b, a);
7612 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7615 void RSurf_SetupDepthAndCulling(void)
7617 // submodels are biased to avoid z-fighting with world surfaces that they
7618 // may be exactly overlapping (avoids z-fighting artifacts on certain
7619 // doors and things in Quake maps)
7620 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7621 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7622 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7623 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7626 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7628 // transparent sky would be ridiculous
7629 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7631 R_SetupGenericShader(false);
7632 skyrenderlater = true;
7633 RSurf_SetupDepthAndCulling();
7635 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7636 // skymasking on them, and Quake3 never did sky masking (unlike
7637 // software Quake and software Quake2), so disable the sky masking
7638 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7639 // and skymasking also looks very bad when noclipping outside the
7640 // level, so don't use it then either.
7641 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7643 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7644 R_Mesh_ColorPointer(NULL, 0, 0);
7645 R_Mesh_ResetTextureState();
7646 if (skyrendermasked)
7648 R_SetupDepthOrShadowShader();
7649 // depth-only (masking)
7650 GL_ColorMask(0,0,0,0);
7651 // just to make sure that braindead drivers don't draw
7652 // anything despite that colormask...
7653 GL_BlendFunc(GL_ZERO, GL_ONE);
7657 R_SetupGenericShader(false);
7659 GL_BlendFunc(GL_ONE, GL_ZERO);
7661 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7662 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7663 if (skyrendermasked)
7664 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7666 R_Mesh_ResetTextureState();
7667 GL_Color(1, 1, 1, 1);
7670 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
7671 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
7672 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
7674 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7677 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7678 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7679 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7680 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7681 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7682 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7683 if (rsurface.texture->backgroundcurrentskinframe)
7685 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7686 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7687 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7688 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7690 if (rsurface.texture->colormapping)
7692 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7693 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7695 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7696 if (r_shadow_usingdeferredprepass)
7698 R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture));
7699 R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture));
7701 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7702 R_Mesh_ColorPointer(NULL, 0, 0);
7704 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7706 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass)
7708 // render background
7709 GL_BlendFunc(GL_ONE, GL_ZERO);
7711 GL_AlphaTest(false);
7713 GL_Color(1, 1, 1, 1);
7714 R_Mesh_ColorPointer(NULL, 0, 0);
7716 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7717 if (r_glsl_permutation)
7719 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7720 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7721 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7722 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7723 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7724 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7725 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);
7727 GL_LockArrays(0, 0);
7729 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7730 GL_DepthMask(false);
7731 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7732 R_Mesh_ColorPointer(NULL, 0, 0);
7734 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7735 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7736 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7739 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
7740 if (!r_glsl_permutation)
7743 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7744 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7745 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7746 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7747 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7749 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7751 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7753 GL_BlendFunc(GL_ONE, GL_ZERO);
7755 GL_AlphaTest(false);
7759 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7760 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7761 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
7764 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7766 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7767 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);
7769 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7773 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7774 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);
7776 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7778 GL_LockArrays(0, 0);
7781 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7783 // OpenGL 1.3 path - anything not completely ancient
7784 int texturesurfaceindex;
7785 qboolean applycolor;
7789 const texturelayer_t *layer;
7790 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7792 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7795 int layertexrgbscale;
7796 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7798 if (layerindex == 0)
7802 GL_AlphaTest(false);
7803 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7806 GL_DepthMask(layer->depthmask && writedepth);
7807 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7808 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7810 layertexrgbscale = 4;
7811 VectorScale(layer->color, 0.25f, layercolor);
7813 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7815 layertexrgbscale = 2;
7816 VectorScale(layer->color, 0.5f, layercolor);
7820 layertexrgbscale = 1;
7821 VectorScale(layer->color, 1.0f, layercolor);
7823 layercolor[3] = layer->color[3];
7824 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7825 R_Mesh_ColorPointer(NULL, 0, 0);
7826 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
7827 switch (layer->type)
7829 case TEXTURELAYERTYPE_LITTEXTURE:
7830 memset(&m, 0, sizeof(m));
7831 m.tex[0] = R_GetTexture(r_texture_white);
7832 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7833 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7834 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7835 m.tex[1] = R_GetTexture(layer->texture);
7836 m.texmatrix[1] = layer->texmatrix;
7837 m.texrgbscale[1] = layertexrgbscale;
7838 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7839 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7840 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7841 R_Mesh_TextureState(&m);
7842 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7843 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7844 else if (rsurface.uselightmaptexture)
7845 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7847 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7849 case TEXTURELAYERTYPE_TEXTURE:
7850 memset(&m, 0, sizeof(m));
7851 m.tex[0] = R_GetTexture(layer->texture);
7852 m.texmatrix[0] = layer->texmatrix;
7853 m.texrgbscale[0] = layertexrgbscale;
7854 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7855 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7856 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7857 R_Mesh_TextureState(&m);
7858 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7860 case TEXTURELAYERTYPE_FOG:
7861 memset(&m, 0, sizeof(m));
7862 m.texrgbscale[0] = layertexrgbscale;
7865 m.tex[0] = R_GetTexture(layer->texture);
7866 m.texmatrix[0] = layer->texmatrix;
7867 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7868 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7869 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7871 R_Mesh_TextureState(&m);
7872 // generate a color array for the fog pass
7873 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7874 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7880 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7881 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)
7883 f = 1 - RSurf_FogVertex(v);
7884 c[0] = layercolor[0];
7885 c[1] = layercolor[1];
7886 c[2] = layercolor[2];
7887 c[3] = f * layercolor[3];
7890 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7893 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7895 GL_LockArrays(0, 0);
7898 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7900 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7901 GL_AlphaTest(false);
7905 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7907 // OpenGL 1.1 - crusty old voodoo path
7908 int texturesurfaceindex;
7912 const texturelayer_t *layer;
7913 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7915 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7917 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7919 if (layerindex == 0)
7923 GL_AlphaTest(false);
7924 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7927 GL_DepthMask(layer->depthmask && writedepth);
7928 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7929 R_Mesh_ColorPointer(NULL, 0, 0);
7930 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
7931 switch (layer->type)
7933 case TEXTURELAYERTYPE_LITTEXTURE:
7934 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7936 // two-pass lit texture with 2x rgbscale
7937 // first the lightmap pass
7938 memset(&m, 0, sizeof(m));
7939 m.tex[0] = R_GetTexture(r_texture_white);
7940 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7941 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7942 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7943 R_Mesh_TextureState(&m);
7944 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7945 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7946 else if (rsurface.uselightmaptexture)
7947 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7949 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7950 GL_LockArrays(0, 0);
7951 // then apply the texture to it
7952 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7953 memset(&m, 0, sizeof(m));
7954 m.tex[0] = R_GetTexture(layer->texture);
7955 m.texmatrix[0] = layer->texmatrix;
7956 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7957 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7958 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7959 R_Mesh_TextureState(&m);
7960 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);
7964 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7965 memset(&m, 0, sizeof(m));
7966 m.tex[0] = R_GetTexture(layer->texture);
7967 m.texmatrix[0] = layer->texmatrix;
7968 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7969 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7970 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7971 R_Mesh_TextureState(&m);
7972 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7973 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);
7975 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);
7978 case TEXTURELAYERTYPE_TEXTURE:
7979 // singletexture unlit texture with transparency support
7980 memset(&m, 0, sizeof(m));
7981 m.tex[0] = R_GetTexture(layer->texture);
7982 m.texmatrix[0] = layer->texmatrix;
7983 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7984 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7985 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7986 R_Mesh_TextureState(&m);
7987 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);
7989 case TEXTURELAYERTYPE_FOG:
7990 // singletexture fogging
7991 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7994 memset(&m, 0, sizeof(m));
7995 m.tex[0] = R_GetTexture(layer->texture);
7996 m.texmatrix[0] = layer->texmatrix;
7997 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7998 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7999 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
8000 R_Mesh_TextureState(&m);
8003 R_Mesh_ResetTextureState();
8004 // generate a color array for the fog pass
8005 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8011 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8012 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)
8014 f = 1 - RSurf_FogVertex(v);
8015 c[0] = layer->color[0];
8016 c[1] = layer->color[1];
8017 c[2] = layer->color[2];
8018 c[3] = f * layer->color[3];
8021 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8024 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8026 GL_LockArrays(0, 0);
8029 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8031 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8032 GL_AlphaTest(false);
8036 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8040 GL_AlphaTest(false);
8041 R_Mesh_ColorPointer(NULL, 0, 0);
8042 R_Mesh_ResetTextureState();
8043 R_SetupGenericShader(false);
8045 if(rsurface.texture && rsurface.texture->currentskinframe)
8047 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8048 c[3] *= rsurface.texture->currentalpha;
8058 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
8060 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8061 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8062 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8065 // brighten it up (as texture value 127 means "unlit")
8066 c[0] *= 2 * r_refdef.view.colorscale;
8067 c[1] *= 2 * r_refdef.view.colorscale;
8068 c[2] *= 2 * r_refdef.view.colorscale;
8070 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8071 c[3] *= r_wateralpha.value;
8073 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8075 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8076 GL_DepthMask(false);
8078 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8080 GL_BlendFunc(GL_ONE, GL_ONE);
8081 GL_DepthMask(false);
8083 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8085 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8086 GL_DepthMask(false);
8088 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8090 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8091 GL_DepthMask(false);
8095 GL_BlendFunc(GL_ONE, GL_ZERO);
8096 GL_DepthMask(writedepth);
8099 rsurface.lightmapcolor4f = NULL;
8101 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8103 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8105 rsurface.lightmapcolor4f = NULL;
8106 rsurface.lightmapcolor4f_bufferobject = 0;
8107 rsurface.lightmapcolor4f_bufferoffset = 0;
8109 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8111 qboolean applycolor = true;
8114 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8116 r_refdef.lightmapintensity = 1;
8117 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8118 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8122 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8124 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8125 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8126 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8129 if(!rsurface.lightmapcolor4f)
8130 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8132 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8133 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8134 if(r_refdef.fogenabled)
8135 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8137 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8138 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8141 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8144 RSurf_SetupDepthAndCulling();
8145 if (r_showsurfaces.integer == 3 && !prepass)
8147 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8150 switch (vid.renderpath)
8152 case RENDERPATH_GL20:
8153 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8155 case RENDERPATH_GL13:
8156 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8158 case RENDERPATH_GL11:
8159 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8165 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8168 RSurf_SetupDepthAndCulling();
8169 if (r_showsurfaces.integer == 3 && !prepass)
8171 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8174 switch (vid.renderpath)
8176 case RENDERPATH_GL20:
8177 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8179 case RENDERPATH_GL13:
8180 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8182 case RENDERPATH_GL11:
8183 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8189 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8192 int texturenumsurfaces, endsurface;
8194 const msurface_t *surface;
8195 const msurface_t *texturesurfacelist[1024];
8197 // if the model is static it doesn't matter what value we give for
8198 // wantnormals and wanttangents, so this logic uses only rules applicable
8199 // to a model, knowing that they are meaningless otherwise
8200 if (ent == r_refdef.scene.worldentity)
8201 RSurf_ActiveWorldEntity();
8202 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8203 RSurf_ActiveModelEntity(ent, false, false, false);
8206 switch (vid.renderpath)
8208 case RENDERPATH_GL20:
8209 RSurf_ActiveModelEntity(ent, true, true, false);
8211 case RENDERPATH_GL13:
8212 case RENDERPATH_GL11:
8213 RSurf_ActiveModelEntity(ent, true, false, false);
8218 if (r_transparentdepthmasking.integer)
8220 qboolean setup = false;
8221 for (i = 0;i < numsurfaces;i = j)
8224 surface = rsurface.modelsurfaces + surfacelist[i];
8225 texture = surface->texture;
8226 rsurface.texture = R_GetCurrentTexture(texture);
8227 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8228 // scan ahead until we find a different texture
8229 endsurface = min(i + 1024, numsurfaces);
8230 texturenumsurfaces = 0;
8231 texturesurfacelist[texturenumsurfaces++] = surface;
8232 for (;j < endsurface;j++)
8234 surface = rsurface.modelsurfaces + surfacelist[j];
8235 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8237 texturesurfacelist[texturenumsurfaces++] = surface;
8239 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
8241 // render the range of surfaces as depth
8245 GL_ColorMask(0,0,0,0);
8248 GL_BlendFunc(GL_ONE, GL_ZERO);
8250 GL_AlphaTest(false);
8251 R_Mesh_ColorPointer(NULL, 0, 0);
8252 R_Mesh_ResetTextureState();
8253 R_SetupDepthOrShadowShader();
8255 RSurf_SetupDepthAndCulling();
8256 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8257 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8260 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8263 for (i = 0;i < numsurfaces;i = j)
8266 surface = rsurface.modelsurfaces + surfacelist[i];
8267 texture = surface->texture;
8268 rsurface.texture = R_GetCurrentTexture(texture);
8269 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8270 // scan ahead until we find a different texture
8271 endsurface = min(i + 1024, numsurfaces);
8272 texturenumsurfaces = 0;
8273 texturesurfacelist[texturenumsurfaces++] = surface;
8274 for (;j < endsurface;j++)
8276 surface = rsurface.modelsurfaces + surfacelist[j];
8277 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8279 texturesurfacelist[texturenumsurfaces++] = surface;
8281 // render the range of surfaces
8282 if (ent == r_refdef.scene.worldentity)
8283 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8285 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8287 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8288 GL_AlphaTest(false);
8291 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
8293 // transparent surfaces get pushed off into the transparent queue
8294 int surfacelistindex;
8295 const msurface_t *surface;
8296 vec3_t tempcenter, center;
8297 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8299 surface = texturesurfacelist[surfacelistindex];
8300 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8301 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8302 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8303 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8304 if (queueentity->transparent_offset) // transparent offset
8306 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8307 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8308 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8310 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8314 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
8316 const entity_render_t *queueentity = r_refdef.scene.worldentity;
8320 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8322 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8324 RSurf_SetupDepthAndCulling();
8325 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8326 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8330 if (!rsurface.texture->currentnumlayers)
8332 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8333 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8335 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8337 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
8339 RSurf_SetupDepthAndCulling();
8340 GL_AlphaTest(false);
8341 R_Mesh_ColorPointer(NULL, 0, 0);
8342 R_Mesh_ResetTextureState();
8343 R_SetupGenericShader(false);
8344 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8346 GL_BlendFunc(GL_ONE, GL_ZERO);
8347 GL_Color(0, 0, 0, 1);
8348 GL_DepthTest(writedepth);
8349 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8351 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
8353 RSurf_SetupDepthAndCulling();
8354 GL_AlphaTest(false);
8355 R_Mesh_ColorPointer(NULL, 0, 0);
8356 R_Mesh_ResetTextureState();
8357 R_SetupGenericShader(false);
8358 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8360 GL_BlendFunc(GL_ONE, GL_ZERO);
8362 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8364 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8365 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8366 else if (!rsurface.texture->currentnumlayers)
8368 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8370 // in the deferred case, transparent surfaces were queued during prepass
8371 if (!r_shadow_usingdeferredprepass)
8372 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8376 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8377 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8382 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8386 // break the surface list down into batches by texture and use of lightmapping
8387 for (i = 0;i < numsurfaces;i = j)
8390 // texture is the base texture pointer, rsurface.texture is the
8391 // current frame/skin the texture is directing us to use (for example
8392 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8393 // use skin 1 instead)
8394 texture = surfacelist[i]->texture;
8395 rsurface.texture = R_GetCurrentTexture(texture);
8396 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8397 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8399 // if this texture is not the kind we want, skip ahead to the next one
8400 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8404 // simply scan ahead until we find a different texture or lightmap state
8405 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8407 // render the range of surfaces
8408 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
8412 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
8417 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8419 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8421 RSurf_SetupDepthAndCulling();
8422 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8423 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8427 if (!rsurface.texture->currentnumlayers)
8429 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8430 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8432 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8434 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8436 RSurf_SetupDepthAndCulling();
8437 GL_AlphaTest(false);
8438 R_Mesh_ColorPointer(NULL, 0, 0);
8439 R_Mesh_ResetTextureState();
8440 R_SetupGenericShader(false);
8441 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8443 GL_BlendFunc(GL_ONE, GL_ZERO);
8444 GL_Color(0, 0, 0, 1);
8445 GL_DepthTest(writedepth);
8446 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8448 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8450 RSurf_SetupDepthAndCulling();
8451 GL_AlphaTest(false);
8452 R_Mesh_ColorPointer(NULL, 0, 0);
8453 R_Mesh_ResetTextureState();
8454 R_SetupGenericShader(false);
8455 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8457 GL_BlendFunc(GL_ONE, GL_ZERO);
8459 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8461 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8462 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8463 else if (!rsurface.texture->currentnumlayers)
8465 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8467 // in the deferred case, transparent surfaces were queued during prepass
8468 if (!r_shadow_usingdeferredprepass)
8469 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8473 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8474 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8479 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8483 // break the surface list down into batches by texture and use of lightmapping
8484 for (i = 0;i < numsurfaces;i = j)
8487 // texture is the base texture pointer, rsurface.texture is the
8488 // current frame/skin the texture is directing us to use (for example
8489 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8490 // use skin 1 instead)
8491 texture = surfacelist[i]->texture;
8492 rsurface.texture = R_GetCurrentTexture(texture);
8493 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8494 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8496 // if this texture is not the kind we want, skip ahead to the next one
8497 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8501 // simply scan ahead until we find a different texture or lightmap state
8502 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8504 // render the range of surfaces
8505 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
8509 float locboxvertex3f[6*4*3] =
8511 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8512 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8513 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8514 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8515 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8516 1,0,0, 0,0,0, 0,1,0, 1,1,0
8519 unsigned short locboxelements[6*2*3] =
8529 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8532 cl_locnode_t *loc = (cl_locnode_t *)ent;
8534 float vertex3f[6*4*3];
8536 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8537 GL_DepthMask(false);
8538 GL_DepthRange(0, 1);
8539 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8541 GL_CullFace(GL_NONE);
8542 R_Mesh_Matrix(&identitymatrix);
8544 R_Mesh_VertexPointer(vertex3f, 0, 0);
8545 R_Mesh_ColorPointer(NULL, 0, 0);
8546 R_Mesh_ResetTextureState();
8547 R_SetupGenericShader(false);
8550 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8551 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8552 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8553 surfacelist[0] < 0 ? 0.5f : 0.125f);
8555 if (VectorCompare(loc->mins, loc->maxs))
8557 VectorSet(size, 2, 2, 2);
8558 VectorMA(loc->mins, -0.5f, size, mins);
8562 VectorCopy(loc->mins, mins);
8563 VectorSubtract(loc->maxs, loc->mins, size);
8566 for (i = 0;i < 6*4*3;)
8567 for (j = 0;j < 3;j++, i++)
8568 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8570 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8573 void R_DrawLocs(void)
8576 cl_locnode_t *loc, *nearestloc;
8578 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8579 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8581 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8582 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8586 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8588 if (decalsystem->decals)
8589 Mem_Free(decalsystem->decals);
8590 memset(decalsystem, 0, sizeof(*decalsystem));
8593 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)
8600 // expand or initialize the system
8601 if (decalsystem->maxdecals <= decalsystem->numdecals)
8603 decalsystem_t old = *decalsystem;
8604 qboolean useshortelements;
8605 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8606 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8607 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)));
8608 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8609 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8610 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8611 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8612 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8613 if (decalsystem->numdecals)
8614 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8616 Mem_Free(old.decals);
8617 for (i = 0;i < decalsystem->maxdecals*3;i++)
8618 decalsystem->element3i[i] = i;
8619 if (useshortelements)
8620 for (i = 0;i < decalsystem->maxdecals*3;i++)
8621 decalsystem->element3s[i] = i;
8624 // grab a decal and search for another free slot for the next one
8625 maxdecals = decalsystem->maxdecals;
8626 decals = decalsystem->decals;
8627 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8628 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8630 decalsystem->freedecal = i;
8631 if (decalsystem->numdecals <= i)
8632 decalsystem->numdecals = i + 1;
8634 // initialize the decal
8636 decal->triangleindex = triangleindex;
8637 decal->surfaceindex = surfaceindex;
8638 decal->decalsequence = decalsequence;
8639 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8640 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8641 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8642 decal->color4ub[0][3] = 255;
8643 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8644 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8645 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8646 decal->color4ub[1][3] = 255;
8647 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8648 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8649 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8650 decal->color4ub[2][3] = 255;
8651 decal->vertex3f[0][0] = v0[0];
8652 decal->vertex3f[0][1] = v0[1];
8653 decal->vertex3f[0][2] = v0[2];
8654 decal->vertex3f[1][0] = v1[0];
8655 decal->vertex3f[1][1] = v1[1];
8656 decal->vertex3f[1][2] = v1[2];
8657 decal->vertex3f[2][0] = v2[0];
8658 decal->vertex3f[2][1] = v2[1];
8659 decal->vertex3f[2][2] = v2[2];
8660 decal->texcoord2f[0][0] = t0[0];
8661 decal->texcoord2f[0][1] = t0[1];
8662 decal->texcoord2f[1][0] = t1[0];
8663 decal->texcoord2f[1][1] = t1[1];
8664 decal->texcoord2f[2][0] = t2[0];
8665 decal->texcoord2f[2][1] = t2[1];
8668 extern cvar_t cl_decals_bias;
8669 extern cvar_t cl_decals_models;
8670 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8671 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)
8673 matrix4x4_t projection;
8674 decalsystem_t *decalsystem;
8676 qboolean notworld = ent != r_refdef.scene.worldentity;
8678 const float *vertex3f;
8679 const msurface_t *surface;
8680 const msurface_t *surfaces;
8681 const int *surfacelist;
8682 const texture_t *texture;
8686 int surfacelistindex;
8689 int decalsurfaceindex;
8694 float localorigin[3];
8695 float localnormal[3];
8706 float points[2][9][3];
8710 decalsystem = &ent->decalsystem;
8712 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8714 R_DecalSystem_Reset(&ent->decalsystem);
8718 if (!model->brush.data_nodes && !cl_decals_models.integer)
8720 if (decalsystem->model)
8721 R_DecalSystem_Reset(decalsystem);
8725 if (decalsystem->model != model)
8726 R_DecalSystem_Reset(decalsystem);
8727 decalsystem->model = model;
8729 RSurf_ActiveModelEntity(ent, false, false, false);
8731 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8732 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8733 VectorNormalize(localnormal);
8734 localsize = worldsize*rsurface.inversematrixscale;
8735 ilocalsize = 1.0f / localsize;
8736 localmins[0] = localorigin[0] - localsize;
8737 localmins[1] = localorigin[1] - localsize;
8738 localmins[2] = localorigin[2] - localsize;
8739 localmaxs[0] = localorigin[0] + localsize;
8740 localmaxs[1] = localorigin[1] + localsize;
8741 localmaxs[2] = localorigin[2] + localsize;
8743 //VectorCopy(localnormal, planes[4]);
8744 //VectorVectors(planes[4], planes[2], planes[0]);
8745 AnglesFromVectors(angles, localnormal, NULL, false);
8746 AngleVectors(angles, planes[0], planes[2], planes[4]);
8747 VectorNegate(planes[0], planes[1]);
8748 VectorNegate(planes[2], planes[3]);
8749 VectorNegate(planes[4], planes[5]);
8750 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8751 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8752 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8753 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8754 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8755 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8760 matrix4x4_t forwardprojection;
8761 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8762 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8767 float projectionvector[4][3];
8768 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8769 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8770 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8771 projectionvector[0][0] = planes[0][0] * ilocalsize;
8772 projectionvector[0][1] = planes[1][0] * ilocalsize;
8773 projectionvector[0][2] = planes[2][0] * ilocalsize;
8774 projectionvector[1][0] = planes[0][1] * ilocalsize;
8775 projectionvector[1][1] = planes[1][1] * ilocalsize;
8776 projectionvector[1][2] = planes[2][1] * ilocalsize;
8777 projectionvector[2][0] = planes[0][2] * ilocalsize;
8778 projectionvector[2][1] = planes[1][2] * ilocalsize;
8779 projectionvector[2][2] = planes[2][2] * ilocalsize;
8780 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8781 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8782 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8783 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8787 dynamic = model->surfmesh.isanimated;
8788 vertex3f = rsurface.modelvertex3f;
8789 numsurfacelist = model->nummodelsurfaces;
8790 surfacelist = model->sortedmodelsurfaces;
8791 surfaces = model->data_surfaces;
8792 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8794 surfaceindex = surfacelist[surfacelistindex];
8795 surface = surfaces + surfaceindex;
8796 // skip transparent surfaces
8797 texture = surface->texture;
8798 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8800 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8802 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8804 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8805 numvertices = surface->num_vertices;
8806 numtriangles = surface->num_triangles;
8807 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8809 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8811 index = 3*e[cornerindex];
8812 VectorCopy(vertex3f + index, v[cornerindex]);
8815 //TriangleNormal(v[0], v[1], v[2], normal);
8816 //if (DotProduct(normal, localnormal) < 0.0f)
8818 // clip by each of the box planes formed from the projection matrix
8819 // if anything survives, we emit the decal
8820 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]);
8823 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]);
8826 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]);
8829 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]);
8832 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]);
8835 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]);
8838 // some part of the triangle survived, so we have to accept it...
8841 // dynamic always uses the original triangle
8843 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8845 index = 3*e[cornerindex];
8846 VectorCopy(vertex3f + index, v[cornerindex]);
8849 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8851 // convert vertex positions to texcoords
8852 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8853 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8854 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8855 // calculate distance fade from the projection origin
8856 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8857 f = bound(0.0f, f, 1.0f);
8858 c[cornerindex][0] = r * f;
8859 c[cornerindex][1] = g * f;
8860 c[cornerindex][2] = b * f;
8861 c[cornerindex][3] = 1.0f;
8862 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8865 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);
8867 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8868 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);
8873 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8874 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)
8876 int renderentityindex;
8879 entity_render_t *ent;
8881 if (!cl_decals_newsystem.integer)
8884 worldmins[0] = worldorigin[0] - worldsize;
8885 worldmins[1] = worldorigin[1] - worldsize;
8886 worldmins[2] = worldorigin[2] - worldsize;
8887 worldmaxs[0] = worldorigin[0] + worldsize;
8888 worldmaxs[1] = worldorigin[1] + worldsize;
8889 worldmaxs[2] = worldorigin[2] + worldsize;
8891 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8893 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8895 ent = r_refdef.scene.entities[renderentityindex];
8896 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8899 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8903 typedef struct r_decalsystem_splatqueue_s
8912 r_decalsystem_splatqueue_t;
8914 int r_decalsystem_numqueued = 0;
8915 #define MAX_DECALSYSTEM_QUEUE 1024
8916 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8918 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)
8920 r_decalsystem_splatqueue_t *queue;
8922 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8925 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8926 VectorCopy(worldorigin, queue->worldorigin);
8927 VectorCopy(worldnormal, queue->worldnormal);
8928 Vector4Set(queue->color, r, g, b, a);
8929 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8930 queue->worldsize = worldsize;
8931 queue->decalsequence = cl.decalsequence++;
8934 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8937 r_decalsystem_splatqueue_t *queue;
8939 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8940 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);
8941 r_decalsystem_numqueued = 0;
8944 extern cvar_t cl_decals_max;
8945 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8948 decalsystem_t *decalsystem = &ent->decalsystem;
8955 if (!decalsystem->numdecals)
8958 if (r_showsurfaces.integer)
8961 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8963 R_DecalSystem_Reset(decalsystem);
8967 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8968 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8970 if (decalsystem->lastupdatetime)
8971 frametime = (cl.time - decalsystem->lastupdatetime);
8974 decalsystem->lastupdatetime = cl.time;
8975 decal = decalsystem->decals;
8976 numdecals = decalsystem->numdecals;
8978 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8980 if (decal->color4ub[0][3])
8982 decal->lived += frametime;
8983 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
8985 memset(decal, 0, sizeof(*decal));
8986 if (decalsystem->freedecal > i)
8987 decalsystem->freedecal = i;
8991 decal = decalsystem->decals;
8992 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
8995 // collapse the array by shuffling the tail decals into the gaps
8998 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
8999 decalsystem->freedecal++;
9000 if (decalsystem->freedecal == numdecals)
9002 decal[decalsystem->freedecal] = decal[--numdecals];
9005 decalsystem->numdecals = numdecals;
9009 // if there are no decals left, reset decalsystem
9010 R_DecalSystem_Reset(decalsystem);
9014 extern skinframe_t *decalskinframe;
9015 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9018 decalsystem_t *decalsystem = &ent->decalsystem;
9028 const unsigned char *surfacevisible = r_refdef.viewcache.world_surfacevisible;
9031 numdecals = decalsystem->numdecals;
9035 if (r_showsurfaces.integer)
9038 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9040 R_DecalSystem_Reset(decalsystem);
9044 // if the model is static it doesn't matter what value we give for
9045 // wantnormals and wanttangents, so this logic uses only rules applicable
9046 // to a model, knowing that they are meaningless otherwise
9047 if (ent == r_refdef.scene.worldentity)
9048 RSurf_ActiveWorldEntity();
9050 RSurf_ActiveModelEntity(ent, false, false, false);
9052 decalsystem->lastupdatetime = cl.time;
9053 decal = decalsystem->decals;
9055 fadedelay = cl_decals_time.value;
9056 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9058 // update vertex positions for animated models
9059 v3f = decalsystem->vertex3f;
9060 c4f = decalsystem->color4f;
9061 t2f = decalsystem->texcoord2f;
9062 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9064 if (!decal->color4ub[0][3])
9067 if (decal->surfaceindex >= 0 && !surfacevisible[decal->surfaceindex])
9070 // update color values for fading decals
9071 if (decal->lived >= cl_decals_time.value)
9073 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9074 alpha *= (1.0f/255.0f);
9077 alpha = 1.0f/255.0f;
9079 c4f[ 0] = decal->color4ub[0][0] * alpha;
9080 c4f[ 1] = decal->color4ub[0][1] * alpha;
9081 c4f[ 2] = decal->color4ub[0][2] * alpha;
9083 c4f[ 4] = decal->color4ub[1][0] * alpha;
9084 c4f[ 5] = decal->color4ub[1][1] * alpha;
9085 c4f[ 6] = decal->color4ub[1][2] * alpha;
9087 c4f[ 8] = decal->color4ub[2][0] * alpha;
9088 c4f[ 9] = decal->color4ub[2][1] * alpha;
9089 c4f[10] = decal->color4ub[2][2] * alpha;
9092 t2f[0] = decal->texcoord2f[0][0];
9093 t2f[1] = decal->texcoord2f[0][1];
9094 t2f[2] = decal->texcoord2f[1][0];
9095 t2f[3] = decal->texcoord2f[1][1];
9096 t2f[4] = decal->texcoord2f[2][0];
9097 t2f[5] = decal->texcoord2f[2][1];
9099 // update vertex positions for animated models
9100 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9102 e = rsurface.modelelement3i + 3*decal->triangleindex;
9103 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9104 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9105 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9109 VectorCopy(decal->vertex3f[0], v3f);
9110 VectorCopy(decal->vertex3f[1], v3f + 3);
9111 VectorCopy(decal->vertex3f[2], v3f + 6);
9122 r_refdef.stats.drawndecals += numtris;
9124 if (r_refdef.fogenabled)
9126 switch(vid.renderpath)
9128 case RENDERPATH_GL20:
9129 case RENDERPATH_GL13:
9130 case RENDERPATH_GL11:
9131 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
9133 alpha = RSurf_FogVertex(v3f);
9142 // now render the decals all at once
9143 // (this assumes they all use one particle font texture!)
9144 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);
9145 R_Mesh_ResetTextureState();
9146 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9147 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9148 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9149 R_SetupGenericShader(true);
9150 GL_DepthMask(false);
9151 GL_DepthRange(0, 1);
9152 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9154 GL_CullFace(GL_NONE);
9155 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9156 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
9157 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
9158 GL_LockArrays(0, numtris * 3);
9159 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9160 GL_LockArrays(0, 0);
9164 static void R_DrawModelDecals(void)
9168 // fade faster when there are too many decals
9169 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9170 for (i = 0;i < r_refdef.scene.numentities;i++)
9171 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9173 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9174 for (i = 0;i < r_refdef.scene.numentities;i++)
9175 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9176 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9178 R_DecalSystem_ApplySplatEntitiesQueue();
9180 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9181 for (i = 0;i < r_refdef.scene.numentities;i++)
9182 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9184 r_refdef.stats.totaldecals += numdecals;
9186 if (r_showsurfaces.integer)
9189 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9191 for (i = 0;i < r_refdef.scene.numentities;i++)
9193 if (!r_refdef.viewcache.entityvisible[i])
9195 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9196 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9200 void R_DrawDebugModel(void)
9202 entity_render_t *ent = rsurface.entity;
9203 int i, j, k, l, flagsmask;
9204 const int *elements;
9206 const msurface_t *surface;
9207 dp_model_t *model = ent->model;
9210 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9212 R_Mesh_ColorPointer(NULL, 0, 0);
9213 R_Mesh_ResetTextureState();
9214 R_SetupGenericShader(false);
9215 GL_DepthRange(0, 1);
9216 GL_DepthTest(!r_showdisabledepthtest.integer);
9217 GL_DepthMask(false);
9218 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9220 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
9222 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9223 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
9225 if (brush->colbrushf && brush->colbrushf->numtriangles)
9227 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
9228 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);
9229 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
9232 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
9234 if (surface->num_collisiontriangles)
9236 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
9237 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);
9238 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
9243 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9245 if (r_showtris.integer || r_shownormals.integer)
9247 if (r_showdisabledepthtest.integer)
9249 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9250 GL_DepthMask(false);
9254 GL_BlendFunc(GL_ONE, GL_ZERO);
9257 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9259 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9261 rsurface.texture = R_GetCurrentTexture(surface->texture);
9262 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9264 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
9265 if (r_showtris.value > 0)
9267 if (!rsurface.texture->currentlayers->depthmask)
9268 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9269 else if (ent == r_refdef.scene.worldentity)
9270 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9272 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9273 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
9274 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
9275 R_Mesh_ColorPointer(NULL, 0, 0);
9276 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
9277 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9278 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
9279 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);
9280 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9283 if (r_shownormals.value < 0)
9286 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9288 VectorCopy(rsurface.vertex3f + l * 3, v);
9289 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9290 qglVertex3f(v[0], v[1], v[2]);
9291 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
9292 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9293 qglVertex3f(v[0], v[1], v[2]);
9298 if (r_shownormals.value > 0)
9301 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9303 VectorCopy(rsurface.vertex3f + l * 3, v);
9304 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9305 qglVertex3f(v[0], v[1], v[2]);
9306 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
9307 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9308 qglVertex3f(v[0], v[1], v[2]);
9313 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9315 VectorCopy(rsurface.vertex3f + l * 3, v);
9316 GL_Color(0, r_refdef.view.colorscale, 0, 1);
9317 qglVertex3f(v[0], v[1], v[2]);
9318 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
9319 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9320 qglVertex3f(v[0], v[1], v[2]);
9325 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9327 VectorCopy(rsurface.vertex3f + l * 3, v);
9328 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9329 qglVertex3f(v[0], v[1], v[2]);
9330 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
9331 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9332 qglVertex3f(v[0], v[1], v[2]);
9339 rsurface.texture = NULL;
9343 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
9344 int r_maxsurfacelist = 0;
9345 const msurface_t **r_surfacelist = NULL;
9346 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9348 int i, j, endj, f, flagsmask;
9350 dp_model_t *model = r_refdef.scene.worldmodel;
9351 msurface_t *surfaces;
9352 unsigned char *update;
9353 int numsurfacelist = 0;
9357 if (r_maxsurfacelist < model->num_surfaces)
9359 r_maxsurfacelist = model->num_surfaces;
9361 Mem_Free((msurface_t**)r_surfacelist);
9362 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9365 RSurf_ActiveWorldEntity();
9367 surfaces = model->data_surfaces;
9368 update = model->brushq1.lightmapupdateflags;
9370 // update light styles on this submodel
9371 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9373 model_brush_lightstyleinfo_t *style;
9374 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9376 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9378 int *list = style->surfacelist;
9379 style->value = r_refdef.scene.lightstylevalue[style->style];
9380 for (j = 0;j < style->numsurfaces;j++)
9381 update[list[j]] = true;
9386 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9391 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9397 rsurface.uselightmaptexture = false;
9398 rsurface.texture = NULL;
9399 rsurface.rtlight = NULL;
9401 // add visible surfaces to draw list
9402 for (i = 0;i < model->nummodelsurfaces;i++)
9404 j = model->sortedmodelsurfaces[i];
9405 if (r_refdef.viewcache.world_surfacevisible[j])
9406 r_surfacelist[numsurfacelist++] = surfaces + j;
9408 // update lightmaps if needed
9410 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9411 if (r_refdef.viewcache.world_surfacevisible[j])
9413 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9414 // don't do anything if there were no surfaces
9415 if (!numsurfacelist)
9417 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9420 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9421 GL_AlphaTest(false);
9423 // add to stats if desired
9424 if (r_speeds.integer && !skysurfaces && !depthonly)
9426 r_refdef.stats.world_surfaces += numsurfacelist;
9427 for (j = 0;j < numsurfacelist;j++)
9428 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9431 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9434 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9436 int i, j, endj, f, flagsmask;
9438 dp_model_t *model = ent->model;
9439 msurface_t *surfaces;
9440 unsigned char *update;
9441 int numsurfacelist = 0;
9445 if (r_maxsurfacelist < model->num_surfaces)
9447 r_maxsurfacelist = model->num_surfaces;
9449 Mem_Free((msurface_t **)r_surfacelist);
9450 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9453 // if the model is static it doesn't matter what value we give for
9454 // wantnormals and wanttangents, so this logic uses only rules applicable
9455 // to a model, knowing that they are meaningless otherwise
9456 if (ent == r_refdef.scene.worldentity)
9457 RSurf_ActiveWorldEntity();
9458 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9459 RSurf_ActiveModelEntity(ent, false, false, false);
9461 RSurf_ActiveModelEntity(ent, true, true, true);
9463 RSurf_ActiveModelEntity(ent, false, false, false);
9466 switch (vid.renderpath)
9468 case RENDERPATH_GL20:
9469 RSurf_ActiveModelEntity(ent, true, true, false);
9471 case RENDERPATH_GL13:
9472 case RENDERPATH_GL11:
9473 RSurf_ActiveModelEntity(ent, true, false, false);
9478 surfaces = model->data_surfaces;
9479 update = model->brushq1.lightmapupdateflags;
9481 // update light styles
9482 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9484 model_brush_lightstyleinfo_t *style;
9485 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9487 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9489 int *list = style->surfacelist;
9490 style->value = r_refdef.scene.lightstylevalue[style->style];
9491 for (j = 0;j < style->numsurfaces;j++)
9492 update[list[j]] = true;
9497 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9502 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9508 rsurface.uselightmaptexture = false;
9509 rsurface.texture = NULL;
9510 rsurface.rtlight = NULL;
9512 // add visible surfaces to draw list
9513 for (i = 0;i < model->nummodelsurfaces;i++)
9514 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9515 // don't do anything if there were no surfaces
9516 if (!numsurfacelist)
9518 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9521 // update lightmaps if needed
9523 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9525 R_BuildLightMap(ent, surfaces + j);
9526 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9527 GL_AlphaTest(false);
9529 // add to stats if desired
9530 if (r_speeds.integer && !skysurfaces && !depthonly)
9532 r_refdef.stats.entities_surfaces += numsurfacelist;
9533 for (j = 0;j < numsurfacelist;j++)
9534 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9537 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9540 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
9542 static texture_t texture;
9543 static msurface_t surface;
9544 const msurface_t *surfacelist = &surface;
9546 // fake enough texture and surface state to render this geometry
9548 texture.update_lastrenderframe = -1; // regenerate this texture
9549 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9550 texture.currentskinframe = skinframe;
9551 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9552 texture.specularscalemod = 1;
9553 texture.specularpowermod = 1;
9555 surface.texture = &texture;
9556 surface.num_triangles = numtriangles;
9557 surface.num_firsttriangle = firsttriangle;
9558 surface.num_vertices = numvertices;
9559 surface.num_firstvertex = firstvertex;
9562 rsurface.texture = R_GetCurrentTexture(surface.texture);
9563 rsurface.uselightmaptexture = false;
9564 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
9567 void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
9569 static msurface_t surface;
9570 const msurface_t *surfacelist = &surface;
9572 // fake enough texture and surface state to render this geometry
9574 surface.texture = texture;
9575 surface.num_triangles = numtriangles;
9576 surface.num_firsttriangle = firsttriangle;
9577 surface.num_vertices = numvertices;
9578 surface.num_firstvertex = firstvertex;
9581 rsurface.texture = R_GetCurrentTexture(surface.texture);
9582 rsurface.uselightmaptexture = false;
9583 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);