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_MultiTexCoord0;\n"
493 " gl_TexCoord[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_MultiTexCoord0;\n"
563 "#ifdef USESPECULAR\n"
564 " gl_TexCoord[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_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 "uniform mat4 TexMatrix;\n"
633 "#ifdef VERTEX_SHADER\n"
637 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
638 " gl_Position = ftransform();\n"
639 " ModelViewProjectionPosition = gl_Position;\n"
643 "#ifdef FRAGMENT_SHADER\n"
644 "uniform sampler2D Texture_Normal;\n"
645 "uniform sampler2D Texture_Refraction;\n"
646 "uniform sampler2D Texture_Reflection;\n"
648 "uniform vec4 DistortScaleRefractReflect;\n"
649 "uniform vec4 ScreenScaleRefractReflect;\n"
650 "uniform vec4 ScreenCenterRefractReflect;\n"
651 "uniform vec4 RefractColor;\n"
652 "uniform vec4 ReflectColor;\n"
653 "uniform float ReflectFactor;\n"
654 "uniform float ReflectOffset;\n"
658 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
659 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
660 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
661 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
662 " // FIXME temporary hack to detect the case that the reflection\n"
663 " // gets blackened at edges due to leaving the area that contains actual\n"
665 " // Remove this 'ack once we have a better way to stop this thing from\n"
667 " float 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 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
671 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
672 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
675 "#else // !MODE_REFRACTION\n"
676 "#ifdef MODE_WATER\n"
677 "varying vec2 TexCoord;\n"
678 "varying vec3 EyeVector;\n"
679 "varying vec4 ModelViewProjectionPosition;\n"
680 "#ifdef VERTEX_SHADER\n"
681 "uniform vec3 EyePosition;\n"
682 "uniform mat4 TexMatrix;\n"
686 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
687 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
688 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
689 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
690 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
691 " gl_Position = ftransform();\n"
692 " ModelViewProjectionPosition = gl_Position;\n"
696 "#ifdef FRAGMENT_SHADER\n"
697 "uniform sampler2D Texture_Normal;\n"
698 "uniform sampler2D Texture_Refraction;\n"
699 "uniform sampler2D Texture_Reflection;\n"
701 "uniform vec4 DistortScaleRefractReflect;\n"
702 "uniform vec4 ScreenScaleRefractReflect;\n"
703 "uniform vec4 ScreenCenterRefractReflect;\n"
704 "uniform vec4 RefractColor;\n"
705 "uniform vec4 ReflectColor;\n"
706 "uniform float ReflectFactor;\n"
707 "uniform float ReflectOffset;\n"
711 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
712 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
713 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
714 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
715 " // FIXME temporary hack to detect the case that the reflection\n"
716 " // gets blackened at edges due to leaving the area that contains actual\n"
718 " // Remove this 'ack once we have a better way to stop this thing from\n"
720 " float 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 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
723 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
724 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\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 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
728 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
729 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
730 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
731 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
734 "#else // !MODE_WATER\n"
736 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
737 "# extension GL_ARB_texture_rectangle : enable\n"
740 "#ifdef USESHADOWMAP2D\n"
741 "# ifdef GL_EXT_gpu_shader4\n"
742 "# extension GL_EXT_gpu_shader4 : enable\n"
744 "# ifdef GL_ARB_texture_gather\n"
745 "# extension GL_ARB_texture_gather : enable\n"
747 "# ifdef GL_AMD_texture_texture4\n"
748 "# extension GL_AMD_texture_texture4 : enable\n"
753 "#ifdef USESHADOWMAPCUBE\n"
754 "# extension GL_EXT_gpu_shader4 : enable\n"
757 "#ifdef USESHADOWSAMPLER\n"
758 "# extension GL_ARB_shadow : enable\n"
761 "// common definitions between vertex shader and fragment shader:\n"
763 "//#ifdef __GLSL_CG_DATA_TYPES\n"
764 "//# define myhalf half\n"
765 "//# define myhalf2 half2\n"
766 "//# define myhalf3half3\n"
767 "//# define myhalf4 half4\n"
769 "# define myhalf float\n"
770 "# define myhalf2 vec2\n"
771 "# define myhalf3 vec3\n"
772 "# define myhalf4 vec4\n"
775 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
779 "varying vec2 TexCoord;\n"
780 "#ifdef USEVERTEXTEXTUREBLEND\n"
781 "varying vec2 TexCoord2;\n"
783 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
784 "#define USELIGHTMAP\n"
785 "varying vec2 TexCoordLightmap;\n"
788 "#ifdef MODE_LIGHTSOURCE\n"
789 "varying vec3 CubeVector;\n"
792 "#ifdef MODE_LIGHTSOURCE\n"
793 "varying vec3 LightVector;\n"
795 "#if defined(MODE_LIGHTDIRECTION)\n"
796 "varying vec3 LightVector;\n"
799 "#if defined(USEOFFSETMAPPING) || defined(USESPECULAR)\n"
800 "//#if defined(USEOFFSETMAPPING) || defined(USESPECULAR) || defined(MODE_LIGHTDIRECTION) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
801 "#define USEEYEVECTOR\n"
802 "varying vec3 EyeVector;\n"
805 "varying vec3 EyeVectorModelSpace;\n"
806 "varying float FogPlaneVertexDist;\n"
809 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
810 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
811 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
812 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
815 "#ifdef USEREFLECTION\n"
816 "varying vec4 ModelViewProjectionPosition;\n"
818 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
819 "uniform vec3 LightPosition;\n"
820 "varying vec4 ModelViewPosition;\n"
823 "#ifdef MODE_LIGHTSOURCE\n"
824 "uniform vec3 LightPosition;\n"
826 "uniform vec3 EyePosition;\n"
827 "#ifdef MODE_LIGHTDIRECTION\n"
828 "uniform vec3 LightDir;\n"
830 "uniform vec4 FogPlane;\n"
836 "// vertex shader specific:\n"
837 "#ifdef VERTEX_SHADER\n"
839 "// 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"
841 "#ifdef MODE_DEFERREDGEOMETRY\n"
842 "uniform mat4 TexMatrix;\n"
843 "#ifdef USEVERTEXTEXTUREBLEND\n"
844 "uniform mat4 BackgroundTexMatrix;\n"
848 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
849 "#ifdef USEVERTEXTEXTUREBLEND\n"
850 " gl_FrontColor = gl_Color;\n"
851 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
854 " // transform unnormalized eye direction into tangent space\n"
855 "#ifdef USEOFFSETMAPPING\n"
856 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
857 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
858 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
859 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
862 " VectorS = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz).xyz;\n"
863 " VectorT = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz).xyz;\n"
864 " VectorR = normalize(gl_NormalMatrix * gl_MultiTexCoord3.xyz).xyz;\n"
865 " gl_Position = ftransform();\n"
867 "#else // !MODE_DEFERREDGEOMETRY\n"
868 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
871 " ModelViewPosition = gl_ModelViewMatrix * gl_Vertex;\n"
872 " gl_Position = ftransform();\n"
874 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
875 "uniform mat4 TexMatrix;\n"
876 "#ifdef USEVERTEXTEXTUREBLEND\n"
877 "uniform mat4 BackgroundTexMatrix;\n"
879 "#ifdef MODE_LIGHTSOURCE\n"
880 "uniform mat4 ModelToLight;\n"
884 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
885 " gl_FrontColor = gl_Color;\n"
887 " // copy the surface texcoord\n"
888 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
889 "#ifdef USEVERTEXTEXTUREBLEND\n"
890 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
892 "#ifdef USELIGHTMAP\n"
893 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
896 "#ifdef MODE_LIGHTSOURCE\n"
897 " // transform vertex position into light attenuation/cubemap space\n"
898 " // (-1 to +1 across the light box)\n"
899 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
901 "# ifdef USEDIFFUSE\n"
902 " // transform unnormalized light direction into tangent space\n"
903 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
904 " // normalize it per pixel)\n"
905 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
906 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
907 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
908 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
912 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
913 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
914 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
915 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
918 " // transform unnormalized eye direction into tangent space\n"
919 "#ifdef USEEYEVECTOR\n"
921 " vec3 EyeVectorModelSpace;\n"
923 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
924 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
925 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
926 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
930 "#ifndef USEEYEVECTOR\n"
931 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
933 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
936 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
937 " VectorS = gl_MultiTexCoord1.xyz;\n"
938 " VectorT = gl_MultiTexCoord2.xyz;\n"
939 " VectorR = gl_MultiTexCoord3.xyz;\n"
942 "//#if defined(USEREFLECTION)\n"
943 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
944 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
945 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
948 "// transform vertex to camera space, using ftransform to match non-VS\n"
950 " gl_Position = ftransform();\n"
952 "#ifdef USEREFLECTION\n"
953 " ModelViewProjectionPosition = gl_Position;\n"
956 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
957 "#endif // !MODE_DEFERREDGEOMETRY\n"
959 "#endif // VERTEX_SHADER\n"
964 "// fragment shader specific:\n"
965 "#ifdef FRAGMENT_SHADER\n"
967 "uniform sampler2D Texture_Normal;\n"
968 "uniform sampler2D Texture_Color;\n"
969 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
970 "uniform sampler2D Texture_Gloss;\n"
973 "uniform sampler2D Texture_Glow;\n"
975 "#ifdef USEVERTEXTEXTUREBLEND\n"
976 "uniform sampler2D Texture_SecondaryNormal;\n"
977 "uniform sampler2D Texture_SecondaryColor;\n"
978 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
979 "uniform sampler2D Texture_SecondaryGloss;\n"
982 "uniform sampler2D Texture_SecondaryGlow;\n"
985 "#ifdef USECOLORMAPPING\n"
986 "uniform sampler2D Texture_Pants;\n"
987 "uniform sampler2D Texture_Shirt;\n"
990 "uniform sampler2D Texture_FogMask;\n"
992 "#ifdef USELIGHTMAP\n"
993 "uniform sampler2D Texture_Lightmap;\n"
995 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
996 "uniform sampler2D Texture_Deluxemap;\n"
998 "#ifdef USEREFLECTION\n"
999 "uniform sampler2D Texture_Reflection;\n"
1002 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1003 "uniform sampler2DRect Texture_ScreenDepth;\n"
1004 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
1006 "#ifdef USEDEFERREDLIGHTMAP\n"
1007 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
1008 "uniform sampler2DRect Texture_ScreenSpecular;\n"
1011 "uniform myhalf3 Color_Pants;\n"
1012 "uniform myhalf3 Color_Shirt;\n"
1013 "uniform myhalf3 FogColor;\n"
1016 "uniform float FogRangeRecip;\n"
1017 "uniform float FogPlaneViewDist;\n"
1018 "uniform float FogHeightFade;\n"
1019 "myhalf FogVertex(void)\n"
1022 "#ifdef USEFOGOUTSIDE\n"
1023 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1025 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1027 " return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1031 "#ifdef USEOFFSETMAPPING\n"
1032 "uniform float OffsetMapping_Scale;\n"
1033 "vec2 OffsetMapping(vec2 TexCoord)\n"
1035 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1036 " // 14 sample relief mapping: linear search and then binary search\n"
1037 " // this basically steps forward a small amount repeatedly until it finds\n"
1038 " // itself inside solid, then jitters forward and back using decreasing\n"
1039 " // amounts to find the impact\n"
1040 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1041 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1042 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1043 " vec3 RT = vec3(TexCoord, 1);\n"
1044 " OffsetVector *= 0.1;\n"
1045 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1046 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1047 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1048 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1049 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1050 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1051 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1052 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1053 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1054 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1055 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1056 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1057 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1058 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1061 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1062 " // this basically moves forward the full distance, and then backs up based\n"
1063 " // on height of samples\n"
1064 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1065 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1066 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1067 " TexCoord += OffsetVector;\n"
1068 " OffsetVector *= 0.333;\n"
1069 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1070 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1071 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1072 " return TexCoord;\n"
1075 "#endif // USEOFFSETMAPPING\n"
1077 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1078 "uniform sampler2D Texture_Attenuation;\n"
1079 "uniform samplerCube Texture_Cube;\n"
1081 "#ifdef USESHADOWMAPRECT\n"
1082 "# ifdef USESHADOWSAMPLER\n"
1083 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1085 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1089 "#ifdef USESHADOWMAP2D\n"
1090 "# ifdef USESHADOWSAMPLER\n"
1091 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1093 "uniform sampler2D Texture_ShadowMap2D;\n"
1097 "#ifdef USESHADOWMAPVSDCT\n"
1098 "uniform samplerCube Texture_CubeProjection;\n"
1101 "#ifdef USESHADOWMAPCUBE\n"
1102 "# ifdef USESHADOWSAMPLER\n"
1103 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1105 "uniform samplerCube Texture_ShadowMapCube;\n"
1109 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1110 "uniform vec2 ShadowMap_TextureScale;\n"
1111 "uniform vec4 ShadowMap_Parameters;\n"
1114 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1115 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1117 " vec3 adir = abs(dir);\n"
1118 "# ifndef USESHADOWMAPVSDCT\n"
1122 " if (adir.x > adir.y)\n"
1124 " if (adir.x > adir.z) // X\n"
1128 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1134 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1139 " if (adir.y > adir.z) // Y\n"
1143 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1149 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1153 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1154 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1155 " stc.z += ShadowMap_Parameters.z;\n"
1158 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1159 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1160 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1161 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1162 " stc.z += ShadowMap_Parameters.z;\n"
1166 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1168 "#ifdef USESHADOWMAPCUBE\n"
1169 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1171 " vec3 adir = abs(dir);\n"
1172 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1176 "# ifdef USESHADOWMAPRECT\n"
1177 "float ShadowMapCompare(vec3 dir)\n"
1179 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1181 "# ifdef USESHADOWSAMPLER\n"
1183 "# ifdef USESHADOWMAPPCF\n"
1184 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1185 " 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"
1187 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1192 "# ifdef USESHADOWMAPPCF\n"
1193 "# if USESHADOWMAPPCF > 1\n"
1194 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1195 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1196 " 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"
1197 " 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"
1198 " 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"
1199 " 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"
1200 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1201 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1203 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1204 " vec2 offset = fract(shadowmaptc.xy);\n"
1205 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1206 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1207 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1208 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1209 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1212 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1220 "# ifdef USESHADOWMAP2D\n"
1221 "float ShadowMapCompare(vec3 dir)\n"
1223 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1226 "# ifdef USESHADOWSAMPLER\n"
1227 "# ifdef USESHADOWMAPPCF\n"
1228 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1229 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1230 " 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"
1232 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1235 "# ifdef USESHADOWMAPPCF\n"
1236 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1237 "# ifdef GL_ARB_texture_gather\n"
1238 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1240 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1242 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1243 " center *= ShadowMap_TextureScale;\n"
1244 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1245 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1246 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1247 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1248 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1249 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1250 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1252 "# ifdef GL_EXT_gpu_shader4\n"
1253 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1255 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1257 "# if USESHADOWMAPPCF > 1\n"
1258 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1259 " center *= ShadowMap_TextureScale;\n"
1260 " 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"
1261 " 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"
1262 " 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"
1263 " 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"
1264 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1265 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1267 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1268 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1269 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1270 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1271 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1272 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1276 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1283 "# ifdef USESHADOWMAPCUBE\n"
1284 "float ShadowMapCompare(vec3 dir)\n"
1286 " // apply depth texture cubemap as light filter\n"
1287 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1289 "# ifdef USESHADOWSAMPLER\n"
1290 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1292 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1297 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1299 "#ifdef MODE_DEFERREDGEOMETRY\n"
1302 "#ifdef USEOFFSETMAPPING\n"
1303 " // apply offsetmapping\n"
1304 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1305 "#define TexCoord TexCoordOffset\n"
1308 "#ifdef USEALPHAKILL\n"
1309 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1313 "#ifdef USEVERTEXTEXTUREBLEND\n"
1314 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1315 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1316 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1317 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1320 "#ifdef USEVERTEXTEXTUREBLEND\n"
1321 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1323 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1326 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1328 "#else // !MODE_DEFERREDGEOMETRY\n"
1329 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1330 "uniform mat4 ViewToLight;\n"
1331 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1332 "uniform vec2 ScreenToDepth;\n"
1333 "uniform myhalf3 DeferredColor_Ambient;\n"
1334 "uniform myhalf3 DeferredColor_Diffuse;\n"
1335 "#ifdef USESPECULAR\n"
1336 "uniform myhalf3 DeferredColor_Specular;\n"
1337 "uniform myhalf SpecularPower;\n"
1341 " // calculate viewspace pixel position\n"
1343 " position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1344 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1345 " // decode viewspace pixel normal\n"
1346 " myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1347 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1348 " // surfacenormal = pixel normal in viewspace\n"
1349 " // LightVector = pixel to light in viewspace\n"
1350 " // CubeVector = position in lightspace\n"
1351 " // eyevector = pixel to view in viewspace\n"
1352 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1353 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1354 "#ifdef USEDIFFUSE\n"
1355 " // calculate diffuse shading\n"
1356 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1357 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1359 "#ifdef USESPECULAR\n"
1360 " // calculate directional shading\n"
1361 " vec3 eyevector = position * -1.0;\n"
1362 "# ifdef USEEXACTSPECULARMATH\n"
1363 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1365 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1366 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1370 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1371 " fade *= ShadowMapCompare(CubeVector);\n"
1374 "#ifdef USEDIFFUSE\n"
1375 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1377 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1379 "#ifdef USESPECULAR\n"
1380 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1382 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1385 "# ifdef USECUBEFILTER\n"
1386 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1387 " gl_FragData[0] *= cubecolor;\n"
1388 " gl_FragData[1] *= cubecolor;\n"
1391 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1392 "#ifdef USEDEFERREDLIGHTMAP\n"
1393 "uniform myhalf3 DeferredMod_Diffuse;\n"
1394 "uniform myhalf3 DeferredMod_Specular;\n"
1396 "uniform myhalf3 Color_Ambient;\n"
1397 "uniform myhalf3 Color_Diffuse;\n"
1398 "uniform myhalf3 Color_Specular;\n"
1399 "uniform myhalf SpecularPower;\n"
1401 "uniform myhalf3 Color_Glow;\n"
1403 "uniform myhalf Alpha;\n"
1404 "#ifdef USEREFLECTION\n"
1405 "uniform vec4 DistortScaleRefractReflect;\n"
1406 "uniform vec4 ScreenScaleRefractReflect;\n"
1407 "uniform vec4 ScreenCenterRefractReflect;\n"
1408 "uniform myhalf4 ReflectColor;\n"
1410 "#ifdef MODE_LIGHTDIRECTION\n"
1411 "uniform myhalf3 LightColor;\n"
1413 "#ifdef MODE_LIGHTSOURCE\n"
1414 "uniform myhalf3 LightColor;\n"
1418 "#ifdef USEOFFSETMAPPING\n"
1419 " // apply offsetmapping\n"
1420 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1421 "#define TexCoord TexCoordOffset\n"
1424 " // combine the diffuse textures (base, pants, shirt)\n"
1425 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1426 "#ifdef USEALPHAKILL\n"
1427 " if (color.a < 0.5)\n"
1430 " color.a *= Alpha;\n"
1431 "#ifdef USECOLORMAPPING\n"
1432 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1434 "#ifdef USEVERTEXTEXTUREBLEND\n"
1435 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1436 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1437 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1438 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1440 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1443 " // get the surface normal\n"
1444 "#ifdef USEVERTEXTEXTUREBLEND\n"
1445 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1447 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1450 " // get the material colors\n"
1451 " myhalf3 diffusetex = color.rgb;\n"
1452 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1453 "# ifdef USEVERTEXTEXTUREBLEND\n"
1454 " myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1456 " myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1463 "#ifdef MODE_LIGHTSOURCE\n"
1464 " // light source\n"
1465 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1466 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1467 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1468 "#ifdef USESPECULAR\n"
1469 "#ifdef USEEXACTSPECULARMATH\n"
1470 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1472 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1473 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1475 " color.rgb += glosstex * (specular * Color_Specular);\n"
1477 " color.rgb *= LightColor;\n"
1478 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1479 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1480 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1482 "# ifdef USECUBEFILTER\n"
1483 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1485 "#endif // MODE_LIGHTSOURCE\n"
1490 "#ifdef MODE_LIGHTDIRECTION\n"
1492 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1493 "#define lightcolor LightColor\n"
1494 "#endif // MODE_LIGHTDIRECTION\n"
1495 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1497 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1498 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1499 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1500 " // convert modelspace light vector to tangentspace\n"
1501 " myhalf3 lightnormal;\n"
1502 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1503 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1504 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1505 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1506 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1507 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1508 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1509 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1510 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1511 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1512 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1513 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1514 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1515 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1516 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1518 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1519 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1520 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1526 "#ifdef MODE_LIGHTMAP\n"
1527 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1528 "#endif // MODE_LIGHTMAP\n"
1529 "#ifdef MODE_VERTEXCOLOR\n"
1530 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1531 "#endif // MODE_VERTEXCOLOR\n"
1532 "#ifdef MODE_FLATCOLOR\n"
1533 " color.rgb = diffusetex * Color_Ambient;\n"
1534 "#endif // MODE_FLATCOLOR\n"
1540 "# ifdef USEDIFFUSE\n"
1541 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1542 "# ifdef USESPECULAR\n"
1543 "# ifdef USEEXACTSPECULARMATH\n"
1544 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1546 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1547 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1549 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1551 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1554 " color.rgb = diffusetex * Color_Ambient;\n"
1558 "#ifdef USEDEFERREDLIGHTMAP\n"
1559 " color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1560 " color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1564 "#ifdef USEVERTEXTEXTUREBLEND\n"
1565 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1567 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1572 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1575 " // 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"
1576 "#ifdef USEREFLECTION\n"
1577 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1578 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1579 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1580 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1581 " // FIXME temporary hack to detect the case that the reflection\n"
1582 " // gets blackened at edges due to leaving the area that contains actual\n"
1584 " // Remove this 'ack once we have a better way to stop this thing from\n"
1586 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1587 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1588 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1589 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1590 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1591 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1594 " gl_FragColor = vec4(color);\n"
1596 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1597 "#endif // !MODE_DEFERREDGEOMETRY\n"
1599 "#endif // FRAGMENT_SHADER\n"
1601 "#endif // !MODE_WATER\n"
1602 "#endif // !MODE_REFRACTION\n"
1603 "#endif // !MODE_BLOOMBLUR\n"
1604 "#endif // !MODE_GENERIC\n"
1605 "#endif // !MODE_POSTPROCESS\n"
1606 "#endif // !MODE_SHOWDEPTH\n"
1607 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1610 typedef struct shaderpermutationinfo_s
1612 const char *pretext;
1615 shaderpermutationinfo_t;
1617 typedef struct shadermodeinfo_s
1619 const char *vertexfilename;
1620 const char *geometryfilename;
1621 const char *fragmentfilename;
1622 const char *pretext;
1627 typedef enum shaderpermutation_e
1629 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1630 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1631 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1632 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1633 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1634 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1635 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1636 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1637 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1638 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1639 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1640 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1641 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1642 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1643 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1644 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1645 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1646 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1647 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1648 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1649 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1650 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1651 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1652 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1653 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1654 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
1655 SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
1656 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
1658 shaderpermutation_t;
1660 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1661 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1663 {"#define USEDIFFUSE\n", " diffuse"},
1664 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1665 {"#define USEVIEWTINT\n", " viewtint"},
1666 {"#define USECOLORMAPPING\n", " colormapping"},
1667 {"#define USESATURATION\n", " saturation"},
1668 {"#define USEFOGINSIDE\n", " foginside"},
1669 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1670 {"#define USEGAMMARAMPS\n", " gammaramps"},
1671 {"#define USECUBEFILTER\n", " cubefilter"},
1672 {"#define USEGLOW\n", " glow"},
1673 {"#define USEBLOOM\n", " bloom"},
1674 {"#define USESPECULAR\n", " specular"},
1675 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1676 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1677 {"#define USEREFLECTION\n", " reflection"},
1678 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1679 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1680 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1681 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1682 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1683 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1684 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1685 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1686 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1687 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1688 {"#define USEALPHAKILL\n", " alphakill"},
1691 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1692 typedef enum shadermode_e
1694 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1695 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1696 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1697 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1698 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1699 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1700 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1701 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1702 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1703 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1704 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1705 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1706 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1707 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1708 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1713 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1714 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1716 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1717 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1718 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1719 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1720 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1721 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1722 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1723 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1724 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1725 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1726 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1727 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1728 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1729 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1730 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1733 struct r_glsl_permutation_s;
1734 typedef struct r_glsl_permutation_s
1736 /// hash lookup data
1737 struct r_glsl_permutation_s *hashnext;
1739 unsigned int permutation;
1741 /// indicates if we have tried compiling this permutation already
1743 /// 0 if compilation failed
1745 /// locations of detected uniforms in program object, or -1 if not found
1746 int loc_Texture_First;
1747 int loc_Texture_Second;
1748 int loc_Texture_GammaRamps;
1749 int loc_Texture_Normal;
1750 int loc_Texture_Color;
1751 int loc_Texture_Gloss;
1752 int loc_Texture_Glow;
1753 int loc_Texture_SecondaryNormal;
1754 int loc_Texture_SecondaryColor;
1755 int loc_Texture_SecondaryGloss;
1756 int loc_Texture_SecondaryGlow;
1757 int loc_Texture_Pants;
1758 int loc_Texture_Shirt;
1759 int loc_Texture_FogMask;
1760 int loc_Texture_Lightmap;
1761 int loc_Texture_Deluxemap;
1762 int loc_Texture_Attenuation;
1763 int loc_Texture_Cube;
1764 int loc_Texture_Refraction;
1765 int loc_Texture_Reflection;
1766 int loc_Texture_ShadowMapRect;
1767 int loc_Texture_ShadowMapCube;
1768 int loc_Texture_ShadowMap2D;
1769 int loc_Texture_CubeProjection;
1770 int loc_Texture_ScreenDepth;
1771 int loc_Texture_ScreenNormalMap;
1772 int loc_Texture_ScreenDiffuse;
1773 int loc_Texture_ScreenSpecular;
1775 int loc_BloomBlur_Parameters;
1777 int loc_Color_Ambient;
1778 int loc_Color_Diffuse;
1779 int loc_Color_Specular;
1781 int loc_Color_Pants;
1782 int loc_Color_Shirt;
1783 int loc_DeferredColor_Ambient;
1784 int loc_DeferredColor_Diffuse;
1785 int loc_DeferredColor_Specular;
1786 int loc_DeferredMod_Diffuse;
1787 int loc_DeferredMod_Specular;
1788 int loc_DistortScaleRefractReflect;
1789 int loc_EyePosition;
1791 int loc_FogHeightFade;
1793 int loc_FogPlaneViewDist;
1794 int loc_FogRangeRecip;
1797 int loc_LightPosition;
1798 int loc_OffsetMapping_Scale;
1800 int loc_ReflectColor;
1801 int loc_ReflectFactor;
1802 int loc_ReflectOffset;
1803 int loc_RefractColor;
1805 int loc_ScreenCenterRefractReflect;
1806 int loc_ScreenScaleRefractReflect;
1807 int loc_ScreenToDepth;
1808 int loc_ShadowMap_Parameters;
1809 int loc_ShadowMap_TextureScale;
1810 int loc_SpecularPower;
1815 int loc_ViewTintColor;
1816 int loc_ViewToLight;
1817 int loc_ModelToLight;
1819 int loc_BackgroundTexMatrix;
1821 r_glsl_permutation_t;
1823 #define SHADERPERMUTATION_HASHSIZE 256
1825 /// information about each possible shader permutation
1826 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1827 /// currently selected permutation
1828 r_glsl_permutation_t *r_glsl_permutation;
1829 /// storage for permutations linked in the hash table
1830 memexpandablearray_t r_glsl_permutationarray;
1832 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1834 //unsigned int hashdepth = 0;
1835 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1836 r_glsl_permutation_t *p;
1837 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1839 if (p->mode == mode && p->permutation == permutation)
1841 //if (hashdepth > 10)
1842 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1847 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1849 p->permutation = permutation;
1850 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1851 r_glsl_permutationhash[mode][hashindex] = p;
1852 //if (hashdepth > 10)
1853 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1857 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1860 if (!filename || !filename[0])
1862 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1865 if (printfromdisknotice)
1866 Con_DPrintf("from disk %s... ", filename);
1867 return shaderstring;
1869 else if (!strcmp(filename, "glsl/default.glsl"))
1871 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1872 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1874 return shaderstring;
1877 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1880 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1881 int vertstrings_count = 0;
1882 int geomstrings_count = 0;
1883 int fragstrings_count = 0;
1884 char *vertexstring, *geometrystring, *fragmentstring;
1885 const char *vertstrings_list[32+3];
1886 const char *geomstrings_list[32+3];
1887 const char *fragstrings_list[32+3];
1888 char permutationname[256];
1895 permutationname[0] = 0;
1896 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1897 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1898 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1900 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1902 // the first pretext is which type of shader to compile as
1903 // (later these will all be bound together as a program object)
1904 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1905 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1906 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1908 // the second pretext is the mode (for example a light source)
1909 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1910 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1911 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1912 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1914 // now add all the permutation pretexts
1915 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1917 if (permutation & (1<<i))
1919 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1920 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1921 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1922 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1926 // keep line numbers correct
1927 vertstrings_list[vertstrings_count++] = "\n";
1928 geomstrings_list[geomstrings_count++] = "\n";
1929 fragstrings_list[fragstrings_count++] = "\n";
1933 // now append the shader text itself
1934 vertstrings_list[vertstrings_count++] = vertexstring;
1935 geomstrings_list[geomstrings_count++] = geometrystring;
1936 fragstrings_list[fragstrings_count++] = fragmentstring;
1938 // if any sources were NULL, clear the respective list
1940 vertstrings_count = 0;
1941 if (!geometrystring)
1942 geomstrings_count = 0;
1943 if (!fragmentstring)
1944 fragstrings_count = 0;
1946 // compile the shader program
1947 if (vertstrings_count + geomstrings_count + fragstrings_count)
1948 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1952 qglUseProgramObjectARB(p->program);CHECKGLERROR
1953 // look up all the uniform variable names we care about, so we don't
1954 // have to look them up every time we set them
1956 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1957 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1958 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1959 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1960 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1961 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1962 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1963 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1964 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1965 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1966 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1967 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1968 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1969 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1970 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1971 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1972 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1973 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1974 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1975 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1976 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1977 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1978 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1979 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1980 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
1981 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
1982 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
1983 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
1984 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
1985 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
1986 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1987 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
1988 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
1989 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
1990 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
1991 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1992 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1993 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
1994 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
1995 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
1996 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
1997 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
1998 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1999 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
2000 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
2001 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
2002 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
2003 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
2004 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
2005 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
2006 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
2007 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
2008 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
2009 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
2010 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
2011 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
2012 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
2013 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
2014 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
2015 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
2016 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2017 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2018 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2019 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2020 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
2021 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
2022 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
2023 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
2024 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
2025 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
2026 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
2027 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
2028 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
2029 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
2030 // initialize the samplers to refer to the texture units we use
2031 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
2032 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
2033 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
2034 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
2035 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
2036 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
2037 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
2038 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2039 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2040 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2041 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
2042 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
2043 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
2044 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
2045 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
2046 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
2047 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
2048 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
2049 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
2050 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
2051 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
2052 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
2053 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
2054 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2055 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
2056 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2057 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
2058 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2060 if (developer.integer)
2061 Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2064 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
2068 Mem_Free(vertexstring);
2070 Mem_Free(geometrystring);
2072 Mem_Free(fragmentstring);
2075 void R_GLSL_Restart_f(void)
2077 unsigned int i, limit;
2078 r_glsl_permutation_t *p;
2079 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2080 for (i = 0;i < limit;i++)
2082 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2084 GL_Backend_FreeProgram(p->program);
2085 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2088 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2091 void R_GLSL_DumpShader_f(void)
2095 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2098 Con_Printf("failed to write to glsl/default.glsl\n");
2102 FS_Print(file, "/* The engine may define the following macros:\n");
2103 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2104 for (i = 0;i < SHADERMODE_COUNT;i++)
2105 FS_Print(file, shadermodeinfo[i].pretext);
2106 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2107 FS_Print(file, shaderpermutationinfo[i].pretext);
2108 FS_Print(file, "*/\n");
2109 FS_Print(file, builtinshaderstring);
2112 Con_Printf("glsl/default.glsl written\n");
2115 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
2117 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2118 if (r_glsl_permutation != perm)
2120 r_glsl_permutation = perm;
2121 if (!r_glsl_permutation->program)
2123 if (!r_glsl_permutation->compiled)
2124 R_GLSL_CompilePermutation(perm, mode, permutation);
2125 if (!r_glsl_permutation->program)
2127 // remove features until we find a valid permutation
2129 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2131 // reduce i more quickly whenever it would not remove any bits
2132 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2133 if (!(permutation & j))
2136 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2137 if (!r_glsl_permutation->compiled)
2138 R_GLSL_CompilePermutation(perm, mode, permutation);
2139 if (r_glsl_permutation->program)
2142 if (i >= SHADERPERMUTATION_COUNT)
2144 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2145 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2146 qglUseProgramObjectARB(0);CHECKGLERROR
2147 return; // no bit left to clear, entire mode is broken
2152 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2156 void R_SetupGenericShader(qboolean usetexture)
2158 switch(vid.renderpath)
2160 case RENDERPATH_GL20:
2161 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2163 case RENDERPATH_GL13:
2164 case RENDERPATH_GL11:
2169 void R_SetupGenericTwoTextureShader(int texturemode)
2171 switch (vid.renderpath)
2173 case RENDERPATH_GL20:
2174 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))));
2176 case RENDERPATH_GL13:
2177 case RENDERPATH_GL11:
2178 R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
2183 void R_SetupDepthOrShadowShader(void)
2185 switch (vid.renderpath)
2187 case RENDERPATH_GL20:
2188 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2190 case RENDERPATH_GL13:
2192 case RENDERPATH_GL11:
2197 void R_SetupShowDepthShader(void)
2199 switch (vid.renderpath)
2201 case RENDERPATH_GL20:
2202 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2204 case RENDERPATH_GL13:
2206 case RENDERPATH_GL11:
2211 extern qboolean r_shadow_usingdeferredprepass;
2212 extern cvar_t r_shadow_deferred_8bitrange;
2213 extern rtexture_t *r_shadow_attenuationgradienttexture;
2214 extern rtexture_t *r_shadow_attenuation2dtexture;
2215 extern rtexture_t *r_shadow_attenuation3dtexture;
2216 extern qboolean r_shadow_usingshadowmaprect;
2217 extern qboolean r_shadow_usingshadowmapcube;
2218 extern qboolean r_shadow_usingshadowmap2d;
2219 extern float r_shadow_shadowmap_texturescale[2];
2220 extern float r_shadow_shadowmap_parameters[4];
2221 extern qboolean r_shadow_shadowmapvsdct;
2222 extern qboolean r_shadow_shadowmapsampler;
2223 extern int r_shadow_shadowmappcf;
2224 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2226 // select a permutation of the lighting shader appropriate to this
2227 // combination of texture, entity, light source, and fogging, only use the
2228 // minimum features necessary to avoid wasting rendering time in the
2229 // fragment shader on features that are not being used
2230 unsigned int permutation = 0;
2231 unsigned int mode = 0;
2233 // TODO: implement geometry-shader based shadow volumes someday
2234 if (r_glsl_offsetmapping.integer)
2236 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2237 if (r_glsl_offsetmapping_reliefmapping.integer)
2238 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2240 if (rsurfacepass == RSURFPASS_BACKGROUND)
2242 // distorted background
2243 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2244 mode = SHADERMODE_WATER;
2246 mode = SHADERMODE_REFRACTION;
2248 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2250 // normalmap (deferred prepass), may use alpha test on diffuse
2251 mode = SHADERMODE_DEFERREDGEOMETRY;
2252 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2253 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2254 if (r_glsl_offsetmapping.integer)
2256 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2257 if (r_glsl_offsetmapping_reliefmapping.integer)
2258 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2261 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2264 mode = SHADERMODE_LIGHTSOURCE;
2265 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2266 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2267 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2268 permutation |= SHADERPERMUTATION_CUBEFILTER;
2269 if (diffusescale > 0)
2270 permutation |= SHADERPERMUTATION_DIFFUSE;
2271 if (specularscale > 0)
2272 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2273 if (r_refdef.fogenabled)
2274 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2275 if (rsurface.texture->colormapping)
2276 permutation |= SHADERPERMUTATION_COLORMAPPING;
2277 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2279 if (r_shadow_usingshadowmaprect)
2280 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2281 if (r_shadow_usingshadowmap2d)
2282 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2283 if (r_shadow_usingshadowmapcube)
2284 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2285 else if(r_shadow_shadowmapvsdct)
2286 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2288 if (r_shadow_shadowmapsampler)
2289 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2290 if (r_shadow_shadowmappcf > 1)
2291 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2292 else if (r_shadow_shadowmappcf)
2293 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2296 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2298 // unshaded geometry (fullbright or ambient model lighting)
2299 mode = SHADERMODE_FLATCOLOR;
2300 ambientscale = diffusescale = specularscale = 0;
2301 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2302 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2303 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2304 permutation |= SHADERPERMUTATION_GLOW;
2305 if (r_refdef.fogenabled)
2306 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2307 if (rsurface.texture->colormapping)
2308 permutation |= SHADERPERMUTATION_COLORMAPPING;
2309 if (r_glsl_offsetmapping.integer)
2311 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2312 if (r_glsl_offsetmapping_reliefmapping.integer)
2313 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2315 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2316 permutation |= SHADERPERMUTATION_REFLECTION;
2318 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2320 // directional 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 permutation |= SHADERPERMUTATION_DIFFUSE;
2327 if (specularscale > 0)
2328 permutation |= SHADERPERMUTATION_SPECULAR;
2329 if (r_refdef.fogenabled)
2330 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2331 if (rsurface.texture->colormapping)
2332 permutation |= SHADERPERMUTATION_COLORMAPPING;
2333 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2334 permutation |= SHADERPERMUTATION_REFLECTION;
2335 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2336 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2338 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2340 // ambient model lighting
2341 mode = SHADERMODE_LIGHTDIRECTION;
2342 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2343 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2344 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2345 permutation |= SHADERPERMUTATION_GLOW;
2346 if (r_refdef.fogenabled)
2347 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2348 if (rsurface.texture->colormapping)
2349 permutation |= SHADERPERMUTATION_COLORMAPPING;
2350 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2351 permutation |= SHADERPERMUTATION_REFLECTION;
2352 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2353 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2358 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2360 // deluxemapping (light direction texture)
2361 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2362 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2364 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2365 permutation |= SHADERPERMUTATION_DIFFUSE;
2366 if (specularscale > 0)
2367 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2369 else if (r_glsl_deluxemapping.integer >= 2)
2371 // fake deluxemapping (uniform light direction in tangentspace)
2372 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2373 permutation |= SHADERPERMUTATION_DIFFUSE;
2374 if (specularscale > 0)
2375 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2377 else if (rsurface.uselightmaptexture)
2379 // ordinary lightmapping (q1bsp, q3bsp)
2380 mode = SHADERMODE_LIGHTMAP;
2384 // ordinary vertex coloring (q3bsp)
2385 mode = SHADERMODE_VERTEXCOLOR;
2387 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2388 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2389 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2390 permutation |= SHADERPERMUTATION_GLOW;
2391 if (r_refdef.fogenabled)
2392 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2393 if (rsurface.texture->colormapping)
2394 permutation |= SHADERPERMUTATION_COLORMAPPING;
2395 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2396 permutation |= SHADERPERMUTATION_REFLECTION;
2397 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2398 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2400 if(permutation & SHADERPERMUTATION_SPECULAR)
2401 if(r_shadow_glossexact.integer)
2402 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2403 if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
2404 permutation |= SHADERPERMUTATION_ALPHAKILL;
2405 R_SetupShader_SetPermutation(mode, permutation);
2406 if (mode == SHADERMODE_LIGHTSOURCE)
2408 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2409 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2410 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2411 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);
2412 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);
2413 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
2415 // additive passes are only darkened by fog, not tinted
2416 if (r_glsl_permutation->loc_FogColor >= 0)
2417 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2418 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]);
2419 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]);
2420 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2424 if (mode == SHADERMODE_FLATCOLOR)
2426 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
2428 else if (mode == SHADERMODE_LIGHTDIRECTION)
2430 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]);
2431 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
2432 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);
2433 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);
2434 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);
2435 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]);
2436 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]);
2440 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]);
2441 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]);
2442 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);
2443 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);
2444 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);
2446 // additive passes are only darkened by fog, not tinted
2447 if (r_glsl_permutation->loc_FogColor >= 0)
2449 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2450 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2452 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2454 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);
2455 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]);
2456 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]);
2457 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2458 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2459 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2460 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2461 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2463 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2464 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2465 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2466 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
2467 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2468 if (r_glsl_permutation->loc_Color_Pants >= 0)
2470 if (rsurface.texture->currentskinframe->pants)
2471 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2473 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2475 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2477 if (rsurface.texture->currentskinframe->shirt)
2478 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2480 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2482 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]);
2483 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2484 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2485 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2486 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2487 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]);
2491 void R_SetupDeferredLightShader(const rtlight_t *rtlight)
2493 // select a permutation of the lighting shader appropriate to this
2494 // combination of texture, entity, light source, and fogging, only use the
2495 // minimum features necessary to avoid wasting rendering time in the
2496 // fragment shader on features that are not being used
2497 unsigned int permutation = 0;
2498 unsigned int mode = 0;
2499 const float *lightcolorbase = rtlight->currentcolor;
2500 float ambientscale = rtlight->ambientscale;
2501 float diffusescale = rtlight->diffusescale;
2502 float specularscale = rtlight->specularscale;
2503 // this is the location of the light in view space
2504 vec3_t viewlightorigin;
2505 // this transforms from view space (camera) to light space (cubemap)
2506 matrix4x4_t viewtolight;
2507 matrix4x4_t lighttoview;
2508 float viewtolight16f[16];
2509 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2511 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2512 if (rtlight->currentcubemap != r_texture_whitecube)
2513 permutation |= SHADERPERMUTATION_CUBEFILTER;
2514 if (diffusescale > 0)
2515 permutation |= SHADERPERMUTATION_DIFFUSE;
2516 if (specularscale > 0)
2518 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2519 if (r_shadow_glossexact.integer)
2520 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2522 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2524 if (r_shadow_usingshadowmaprect)
2525 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2526 if (r_shadow_usingshadowmap2d)
2527 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2528 if (r_shadow_usingshadowmapcube)
2529 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2530 else if(r_shadow_shadowmapvsdct)
2531 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2533 if (r_shadow_shadowmapsampler)
2534 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2535 if (r_shadow_shadowmappcf > 1)
2536 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2537 else if (r_shadow_shadowmappcf)
2538 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2540 R_SetupShader_SetPermutation(mode, permutation);
2541 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2542 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2543 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2544 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2545 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2546 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight, 1, false, viewtolight16f);
2547 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);
2548 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);
2549 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);
2550 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]);
2551 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]);
2552 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));
2553 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]);
2556 #define SKINFRAME_HASH 1024
2560 int loadsequence; // incremented each level change
2561 memexpandablearray_t array;
2562 skinframe_t *hash[SKINFRAME_HASH];
2565 r_skinframe_t r_skinframe;
2567 void R_SkinFrame_PrepareForPurge(void)
2569 r_skinframe.loadsequence++;
2570 // wrap it without hitting zero
2571 if (r_skinframe.loadsequence >= 200)
2572 r_skinframe.loadsequence = 1;
2575 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2579 // mark the skinframe as used for the purging code
2580 skinframe->loadsequence = r_skinframe.loadsequence;
2583 void R_SkinFrame_Purge(void)
2587 for (i = 0;i < SKINFRAME_HASH;i++)
2589 for (s = r_skinframe.hash[i];s;s = s->next)
2591 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2593 if (s->merged == s->base)
2595 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2596 R_PurgeTexture(s->stain );s->stain = NULL;
2597 R_PurgeTexture(s->merged);s->merged = NULL;
2598 R_PurgeTexture(s->base );s->base = NULL;
2599 R_PurgeTexture(s->pants );s->pants = NULL;
2600 R_PurgeTexture(s->shirt );s->shirt = NULL;
2601 R_PurgeTexture(s->nmap );s->nmap = NULL;
2602 R_PurgeTexture(s->gloss );s->gloss = NULL;
2603 R_PurgeTexture(s->glow );s->glow = NULL;
2604 R_PurgeTexture(s->fog );s->fog = NULL;
2605 s->loadsequence = 0;
2611 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2613 char basename[MAX_QPATH];
2615 Image_StripImageExtension(name, basename, sizeof(basename));
2617 if( last == NULL ) {
2619 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2620 item = r_skinframe.hash[hashindex];
2625 // linearly search through the hash bucket
2626 for( ; item ; item = item->next ) {
2627 if( !strcmp( item->basename, basename ) ) {
2634 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2638 char basename[MAX_QPATH];
2640 Image_StripImageExtension(name, basename, sizeof(basename));
2642 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2643 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2644 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2648 rtexture_t *dyntexture;
2649 // check whether its a dynamic texture
2650 dyntexture = CL_GetDynTexture( basename );
2651 if (!add && !dyntexture)
2653 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2654 memset(item, 0, sizeof(*item));
2655 strlcpy(item->basename, basename, sizeof(item->basename));
2656 item->base = dyntexture; // either NULL or dyntexture handle
2657 item->textureflags = textureflags;
2658 item->comparewidth = comparewidth;
2659 item->compareheight = compareheight;
2660 item->comparecrc = comparecrc;
2661 item->next = r_skinframe.hash[hashindex];
2662 r_skinframe.hash[hashindex] = item;
2664 else if( item->base == NULL )
2666 rtexture_t *dyntexture;
2667 // check whether its a dynamic texture
2668 // 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]
2669 dyntexture = CL_GetDynTexture( basename );
2670 item->base = dyntexture; // either NULL or dyntexture handle
2673 R_SkinFrame_MarkUsed(item);
2677 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2679 unsigned long long avgcolor[5], wsum; \
2687 for(pix = 0; pix < cnt; ++pix) \
2690 for(comp = 0; comp < 3; ++comp) \
2692 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2695 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2697 for(comp = 0; comp < 3; ++comp) \
2698 avgcolor[comp] += getpixel * w; \
2701 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2702 avgcolor[4] += getpixel; \
2704 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2706 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2707 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2708 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2709 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2712 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2715 unsigned char *pixels;
2716 unsigned char *bumppixels;
2717 unsigned char *basepixels = NULL;
2718 int basepixels_width;
2719 int basepixels_height;
2720 skinframe_t *skinframe;
2722 if (cls.state == ca_dedicated)
2725 // return an existing skinframe if already loaded
2726 // if loading of the first image fails, don't make a new skinframe as it
2727 // would cause all future lookups of this to be missing
2728 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2729 if (skinframe && skinframe->base)
2732 basepixels = loadimagepixelsbgra(name, complain, true);
2733 if (basepixels == NULL)
2736 if (developer_loading.integer)
2737 Con_Printf("loading skin \"%s\"\n", name);
2739 // we've got some pixels to store, so really allocate this new texture now
2741 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2742 skinframe->stain = NULL;
2743 skinframe->merged = NULL;
2744 skinframe->base = r_texture_notexture;
2745 skinframe->pants = NULL;
2746 skinframe->shirt = NULL;
2747 skinframe->nmap = r_texture_blanknormalmap;
2748 skinframe->gloss = NULL;
2749 skinframe->glow = NULL;
2750 skinframe->fog = NULL;
2751 skinframe->hasalpha = false;
2753 basepixels_width = image_width;
2754 basepixels_height = image_height;
2755 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);
2757 if (textureflags & TEXF_ALPHA)
2759 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2761 if (basepixels[j] < 255)
2763 skinframe->hasalpha = true;
2767 if (r_loadfog && skinframe->hasalpha)
2769 // has transparent pixels
2770 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2771 for (j = 0;j < image_width * image_height * 4;j += 4)
2776 pixels[j+3] = basepixels[j+3];
2778 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);
2783 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2784 //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]);
2786 // _norm is the name used by tenebrae and has been adopted as standard
2787 if (r_loadnormalmap)
2789 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2791 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);
2795 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2797 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2798 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2799 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);
2801 Mem_Free(bumppixels);
2803 else if (r_shadow_bumpscale_basetexture.value > 0)
2805 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2806 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2807 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);
2811 // _luma is supported for tenebrae compatibility
2812 // (I think it's a very stupid name, but oh well)
2813 // _glow is the preferred name
2814 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;}
2815 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;}
2816 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;}
2817 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;}
2820 Mem_Free(basepixels);
2825 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2826 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2829 unsigned char *temp1, *temp2;
2830 skinframe_t *skinframe;
2832 if (cls.state == ca_dedicated)
2835 // if already loaded just return it, otherwise make a new skinframe
2836 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2837 if (skinframe && skinframe->base)
2840 skinframe->stain = NULL;
2841 skinframe->merged = NULL;
2842 skinframe->base = r_texture_notexture;
2843 skinframe->pants = NULL;
2844 skinframe->shirt = NULL;
2845 skinframe->nmap = r_texture_blanknormalmap;
2846 skinframe->gloss = NULL;
2847 skinframe->glow = NULL;
2848 skinframe->fog = NULL;
2849 skinframe->hasalpha = false;
2851 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2855 if (developer_loading.integer)
2856 Con_Printf("loading 32bit skin \"%s\"\n", name);
2858 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2860 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2861 temp2 = temp1 + width * height * 4;
2862 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2863 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2866 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2867 if (textureflags & TEXF_ALPHA)
2869 for (i = 3;i < width * height * 4;i += 4)
2871 if (skindata[i] < 255)
2873 skinframe->hasalpha = true;
2877 if (r_loadfog && skinframe->hasalpha)
2879 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2880 memcpy(fogpixels, skindata, width * height * 4);
2881 for (i = 0;i < width * height * 4;i += 4)
2882 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2883 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2884 Mem_Free(fogpixels);
2888 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2889 //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]);
2894 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2898 skinframe_t *skinframe;
2900 if (cls.state == ca_dedicated)
2903 // if already loaded just return it, otherwise make a new skinframe
2904 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2905 if (skinframe && skinframe->base)
2908 skinframe->stain = NULL;
2909 skinframe->merged = NULL;
2910 skinframe->base = r_texture_notexture;
2911 skinframe->pants = NULL;
2912 skinframe->shirt = NULL;
2913 skinframe->nmap = r_texture_blanknormalmap;
2914 skinframe->gloss = NULL;
2915 skinframe->glow = NULL;
2916 skinframe->fog = NULL;
2917 skinframe->hasalpha = false;
2919 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2923 if (developer_loading.integer)
2924 Con_Printf("loading quake skin \"%s\"\n", name);
2926 // 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)
2927 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
2928 memcpy(skinframe->qpixels, skindata, width*height);
2929 skinframe->qwidth = width;
2930 skinframe->qheight = height;
2933 for (i = 0;i < width * height;i++)
2934 featuresmask |= palette_featureflags[skindata[i]];
2936 skinframe->hasalpha = false;
2937 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2938 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2939 skinframe->qgeneratemerged = true;
2940 skinframe->qgeneratebase = skinframe->qhascolormapping;
2941 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2943 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2944 //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]);
2949 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2953 unsigned char *skindata;
2955 if (!skinframe->qpixels)
2958 if (!skinframe->qhascolormapping)
2959 colormapped = false;
2963 if (!skinframe->qgeneratebase)
2968 if (!skinframe->qgeneratemerged)
2972 width = skinframe->qwidth;
2973 height = skinframe->qheight;
2974 skindata = skinframe->qpixels;
2976 if (skinframe->qgeneratenmap)
2978 unsigned char *temp1, *temp2;
2979 skinframe->qgeneratenmap = false;
2980 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2981 temp2 = temp1 + width * height * 4;
2982 // use either a custom palette or the quake palette
2983 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2984 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2985 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2989 if (skinframe->qgenerateglow)
2991 skinframe->qgenerateglow = false;
2992 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
2997 skinframe->qgeneratebase = false;
2998 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);
2999 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
3000 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
3004 skinframe->qgeneratemerged = false;
3005 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3008 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3010 Mem_Free(skinframe->qpixels);
3011 skinframe->qpixels = NULL;
3015 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)
3018 skinframe_t *skinframe;
3020 if (cls.state == ca_dedicated)
3023 // if already loaded just return it, otherwise make a new skinframe
3024 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3025 if (skinframe && skinframe->base)
3028 skinframe->stain = NULL;
3029 skinframe->merged = NULL;
3030 skinframe->base = r_texture_notexture;
3031 skinframe->pants = NULL;
3032 skinframe->shirt = NULL;
3033 skinframe->nmap = r_texture_blanknormalmap;
3034 skinframe->gloss = NULL;
3035 skinframe->glow = NULL;
3036 skinframe->fog = NULL;
3037 skinframe->hasalpha = false;
3039 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3043 if (developer_loading.integer)
3044 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3046 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3047 if (textureflags & TEXF_ALPHA)
3049 for (i = 0;i < width * height;i++)
3051 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3053 skinframe->hasalpha = true;
3057 if (r_loadfog && skinframe->hasalpha)
3058 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3061 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3062 //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]);
3067 skinframe_t *R_SkinFrame_LoadMissing(void)
3069 skinframe_t *skinframe;
3071 if (cls.state == ca_dedicated)
3074 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
3075 skinframe->stain = NULL;
3076 skinframe->merged = NULL;
3077 skinframe->base = r_texture_notexture;
3078 skinframe->pants = NULL;
3079 skinframe->shirt = NULL;
3080 skinframe->nmap = r_texture_blanknormalmap;
3081 skinframe->gloss = NULL;
3082 skinframe->glow = NULL;
3083 skinframe->fog = NULL;
3084 skinframe->hasalpha = false;
3086 skinframe->avgcolor[0] = rand() / RAND_MAX;
3087 skinframe->avgcolor[1] = rand() / RAND_MAX;
3088 skinframe->avgcolor[2] = rand() / RAND_MAX;
3089 skinframe->avgcolor[3] = 1;
3094 void R_Main_FreeViewCache(void)
3096 if (r_refdef.viewcache.entityvisible)
3097 Mem_Free(r_refdef.viewcache.entityvisible);
3098 if (r_refdef.viewcache.world_pvsbits)
3099 Mem_Free(r_refdef.viewcache.world_pvsbits);
3100 if (r_refdef.viewcache.world_leafvisible)
3101 Mem_Free(r_refdef.viewcache.world_leafvisible);
3102 if (r_refdef.viewcache.world_surfacevisible)
3103 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3104 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3107 void R_Main_ResizeViewCache(void)
3109 int numentities = r_refdef.scene.numentities;
3110 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3111 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3112 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3113 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3114 if (r_refdef.viewcache.maxentities < numentities)
3116 r_refdef.viewcache.maxentities = numentities;
3117 if (r_refdef.viewcache.entityvisible)
3118 Mem_Free(r_refdef.viewcache.entityvisible);
3119 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3121 if (r_refdef.viewcache.world_numclusters != numclusters)
3123 r_refdef.viewcache.world_numclusters = numclusters;
3124 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3125 if (r_refdef.viewcache.world_pvsbits)
3126 Mem_Free(r_refdef.viewcache.world_pvsbits);
3127 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3129 if (r_refdef.viewcache.world_numleafs != numleafs)
3131 r_refdef.viewcache.world_numleafs = numleafs;
3132 if (r_refdef.viewcache.world_leafvisible)
3133 Mem_Free(r_refdef.viewcache.world_leafvisible);
3134 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3136 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3138 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3139 if (r_refdef.viewcache.world_surfacevisible)
3140 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3141 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3145 extern rtexture_t *loadingscreentexture;
3146 void gl_main_start(void)
3148 loadingscreentexture = NULL;
3149 r_texture_blanknormalmap = NULL;
3150 r_texture_white = NULL;
3151 r_texture_grey128 = NULL;
3152 r_texture_black = NULL;
3153 r_texture_whitecube = NULL;
3154 r_texture_normalizationcube = NULL;
3155 r_texture_fogattenuation = NULL;
3156 r_texture_gammaramps = NULL;
3158 switch(vid.renderpath)
3160 case RENDERPATH_GL20:
3161 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3162 Cvar_SetValueQuick(&gl_combine, 1);
3163 Cvar_SetValueQuick(&r_glsl, 1);
3164 r_loadnormalmap = true;
3168 case RENDERPATH_GL13:
3169 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3170 Cvar_SetValueQuick(&gl_combine, 1);
3171 Cvar_SetValueQuick(&r_glsl, 0);
3172 r_loadnormalmap = false;
3173 r_loadgloss = false;
3176 case RENDERPATH_GL11:
3177 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3178 Cvar_SetValueQuick(&gl_combine, 0);
3179 Cvar_SetValueQuick(&r_glsl, 0);
3180 r_loadnormalmap = false;
3181 r_loadgloss = false;
3187 R_FrameData_Reset();
3191 memset(r_queries, 0, sizeof(r_queries));
3193 r_qwskincache = NULL;
3194 r_qwskincache_size = 0;
3196 // set up r_skinframe loading system for textures
3197 memset(&r_skinframe, 0, sizeof(r_skinframe));
3198 r_skinframe.loadsequence = 1;
3199 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3201 r_main_texturepool = R_AllocTexturePool();
3202 R_BuildBlankTextures();
3204 if (vid.support.arb_texture_cube_map)
3207 R_BuildNormalizationCube();
3209 r_texture_fogattenuation = NULL;
3210 r_texture_gammaramps = NULL;
3211 //r_texture_fogintensity = NULL;
3212 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3213 memset(&r_waterstate, 0, sizeof(r_waterstate));
3214 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3215 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3216 memset(&r_svbsp, 0, sizeof (r_svbsp));
3218 r_refdef.fogmasktable_density = 0;
3221 void gl_main_shutdown(void)
3224 R_FrameData_Reset();
3226 R_Main_FreeViewCache();
3229 qglDeleteQueriesARB(r_maxqueries, r_queries);
3233 memset(r_queries, 0, sizeof(r_queries));
3235 r_qwskincache = NULL;
3236 r_qwskincache_size = 0;
3238 // clear out the r_skinframe state
3239 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3240 memset(&r_skinframe, 0, sizeof(r_skinframe));
3243 Mem_Free(r_svbsp.nodes);
3244 memset(&r_svbsp, 0, sizeof (r_svbsp));
3245 R_FreeTexturePool(&r_main_texturepool);
3246 loadingscreentexture = NULL;
3247 r_texture_blanknormalmap = NULL;
3248 r_texture_white = NULL;
3249 r_texture_grey128 = NULL;
3250 r_texture_black = NULL;
3251 r_texture_whitecube = NULL;
3252 r_texture_normalizationcube = NULL;
3253 r_texture_fogattenuation = NULL;
3254 r_texture_gammaramps = NULL;
3255 //r_texture_fogintensity = NULL;
3256 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3257 memset(&r_waterstate, 0, sizeof(r_waterstate));
3261 extern void CL_ParseEntityLump(char *entitystring);
3262 void gl_main_newmap(void)
3264 // FIXME: move this code to client
3266 char *entities, entname[MAX_QPATH];
3268 Mem_Free(r_qwskincache);
3269 r_qwskincache = NULL;
3270 r_qwskincache_size = 0;
3273 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
3274 l = (int)strlen(entname) - 4;
3275 if (l >= 0 && !strcmp(entname + l, ".bsp"))
3277 memcpy(entname + l, ".ent", 5);
3278 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3280 CL_ParseEntityLump(entities);
3285 if (cl.worldmodel->brush.entities)
3286 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3288 R_Main_FreeViewCache();
3290 R_FrameData_Reset();
3293 void GL_Main_Init(void)
3295 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3297 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3298 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3299 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3300 if (gamemode == GAME_NEHAHRA)
3302 Cvar_RegisterVariable (&gl_fogenable);
3303 Cvar_RegisterVariable (&gl_fogdensity);
3304 Cvar_RegisterVariable (&gl_fogred);
3305 Cvar_RegisterVariable (&gl_foggreen);
3306 Cvar_RegisterVariable (&gl_fogblue);
3307 Cvar_RegisterVariable (&gl_fogstart);
3308 Cvar_RegisterVariable (&gl_fogend);
3309 Cvar_RegisterVariable (&gl_skyclip);
3311 Cvar_RegisterVariable(&r_motionblur);
3312 Cvar_RegisterVariable(&r_motionblur_maxblur);
3313 Cvar_RegisterVariable(&r_motionblur_bmin);
3314 Cvar_RegisterVariable(&r_motionblur_vmin);
3315 Cvar_RegisterVariable(&r_motionblur_vmax);
3316 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3317 Cvar_RegisterVariable(&r_motionblur_randomize);
3318 Cvar_RegisterVariable(&r_damageblur);
3319 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3320 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3321 Cvar_RegisterVariable(&r_equalize_entities_by);
3322 Cvar_RegisterVariable(&r_equalize_entities_to);
3323 Cvar_RegisterVariable(&r_depthfirst);
3324 Cvar_RegisterVariable(&r_useinfinitefarclip);
3325 Cvar_RegisterVariable(&r_farclip_base);
3326 Cvar_RegisterVariable(&r_farclip_world);
3327 Cvar_RegisterVariable(&r_nearclip);
3328 Cvar_RegisterVariable(&r_showbboxes);
3329 Cvar_RegisterVariable(&r_showsurfaces);
3330 Cvar_RegisterVariable(&r_showtris);
3331 Cvar_RegisterVariable(&r_shownormals);
3332 Cvar_RegisterVariable(&r_showlighting);
3333 Cvar_RegisterVariable(&r_showshadowvolumes);
3334 Cvar_RegisterVariable(&r_showcollisionbrushes);
3335 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3336 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3337 Cvar_RegisterVariable(&r_showdisabledepthtest);
3338 Cvar_RegisterVariable(&r_drawportals);
3339 Cvar_RegisterVariable(&r_drawentities);
3340 Cvar_RegisterVariable(&r_cullentities_trace);
3341 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3342 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3343 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3344 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3345 Cvar_RegisterVariable(&r_drawviewmodel);
3346 Cvar_RegisterVariable(&r_speeds);
3347 Cvar_RegisterVariable(&r_fullbrights);
3348 Cvar_RegisterVariable(&r_wateralpha);
3349 Cvar_RegisterVariable(&r_dynamic);
3350 Cvar_RegisterVariable(&r_fullbright);
3351 Cvar_RegisterVariable(&r_shadows);
3352 Cvar_RegisterVariable(&r_shadows_darken);
3353 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3354 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3355 Cvar_RegisterVariable(&r_shadows_throwdistance);
3356 Cvar_RegisterVariable(&r_shadows_throwdirection);
3357 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3358 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3359 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3360 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3361 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3362 Cvar_RegisterVariable(&r_fog_exp2);
3363 Cvar_RegisterVariable(&r_drawfog);
3364 Cvar_RegisterVariable(&r_transparentdepthmasking);
3365 Cvar_RegisterVariable(&r_textureunits);
3366 Cvar_RegisterVariable(&gl_combine);
3367 Cvar_RegisterVariable(&r_glsl);
3368 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3369 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3370 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3371 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3372 Cvar_RegisterVariable(&r_glsl_postprocess);
3373 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3374 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3375 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3376 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3377 Cvar_RegisterVariable(&r_water);
3378 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3379 Cvar_RegisterVariable(&r_water_clippingplanebias);
3380 Cvar_RegisterVariable(&r_water_refractdistort);
3381 Cvar_RegisterVariable(&r_water_reflectdistort);
3382 Cvar_RegisterVariable(&r_lerpsprites);
3383 Cvar_RegisterVariable(&r_lerpmodels);
3384 Cvar_RegisterVariable(&r_lerplightstyles);
3385 Cvar_RegisterVariable(&r_waterscroll);
3386 Cvar_RegisterVariable(&r_bloom);
3387 Cvar_RegisterVariable(&r_bloom_colorscale);
3388 Cvar_RegisterVariable(&r_bloom_brighten);
3389 Cvar_RegisterVariable(&r_bloom_blur);
3390 Cvar_RegisterVariable(&r_bloom_resolution);
3391 Cvar_RegisterVariable(&r_bloom_colorexponent);
3392 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3393 Cvar_RegisterVariable(&r_hdr);
3394 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3395 Cvar_RegisterVariable(&r_hdr_glowintensity);
3396 Cvar_RegisterVariable(&r_hdr_range);
3397 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3398 Cvar_RegisterVariable(&developer_texturelogging);
3399 Cvar_RegisterVariable(&gl_lightmaps);
3400 Cvar_RegisterVariable(&r_test);
3401 Cvar_RegisterVariable(&r_batchmode);
3402 Cvar_RegisterVariable(&r_glsl_saturation);
3403 Cvar_RegisterVariable(&r_framedatasize);
3404 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3405 Cvar_SetValue("r_fullbrights", 0);
3406 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3408 Cvar_RegisterVariable(&r_track_sprites);
3409 Cvar_RegisterVariable(&r_track_sprites_flags);
3410 Cvar_RegisterVariable(&r_track_sprites_scalew);
3411 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3414 extern void R_Textures_Init(void);
3415 extern void GL_Draw_Init(void);
3416 extern void GL_Main_Init(void);
3417 extern void R_Shadow_Init(void);
3418 extern void R_Sky_Init(void);
3419 extern void GL_Surf_Init(void);
3420 extern void R_Particles_Init(void);
3421 extern void R_Explosion_Init(void);
3422 extern void gl_backend_init(void);
3423 extern void Sbar_Init(void);
3424 extern void R_LightningBeams_Init(void);
3425 extern void Mod_RenderInit(void);
3427 void Render_Init(void)
3439 R_LightningBeams_Init();
3448 extern char *ENGINE_EXTENSIONS;
3451 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3452 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3453 gl_version = (const char *)qglGetString(GL_VERSION);
3454 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3458 if (!gl_platformextensions)
3459 gl_platformextensions = "";
3461 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3462 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3463 Con_Printf("GL_VERSION: %s\n", gl_version);
3464 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3465 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3467 VID_CheckExtensions();
3469 // LordHavoc: report supported extensions
3470 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3472 // clear to black (loading plaque will be seen over this)
3474 qglClearColor(0,0,0,1);CHECKGLERROR
3475 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3478 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3482 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3484 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3487 p = r_refdef.view.frustum + i;
3492 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3496 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3500 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3504 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3508 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3512 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3516 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3520 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3528 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3532 for (i = 0;i < numplanes;i++)
3539 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3543 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3547 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3551 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3555 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3559 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3563 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3567 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3575 //==================================================================================
3577 // LordHavoc: this stores temporary data used within the same frame
3579 qboolean r_framedata_failed;
3580 static size_t r_framedata_size;
3581 static size_t r_framedata_current;
3582 static void *r_framedata_base;
3584 void R_FrameData_Reset(void)
3586 if (r_framedata_base);
3587 Mem_Free(r_framedata_base);
3588 r_framedata_base = NULL;
3589 r_framedata_size = 0;
3590 r_framedata_current = 0;
3591 r_framedata_failed = false;
3594 void R_FrameData_NewFrame(void)
3597 if (r_framedata_failed)
3598 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
3599 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
3600 wantedsize = bound(65536, wantedsize, 128*1024*1024);
3601 if (r_framedata_size != wantedsize)
3603 r_framedata_size = wantedsize;
3604 if (r_framedata_base);
3605 Mem_Free(r_framedata_base);
3606 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
3608 r_framedata_current = 0;
3609 r_framedata_failed = false;
3612 void *R_FrameData_Alloc(size_t size)
3616 // align to 16 byte boundary
3617 size = (size + 15) & ~15;
3618 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
3619 r_framedata_current += size;
3622 if (r_framedata_current > r_framedata_size)
3623 r_framedata_failed = true;
3625 // return NULL on everything after a failure
3626 if (r_framedata_failed)
3632 void *R_FrameData_Store(size_t size, void *data)
3634 void *d = R_FrameData_Alloc(size);
3636 memcpy(d, data, size);
3640 //==================================================================================
3642 // LordHavoc: animcache originally written by Echon, rewritten since then
3645 * Animation cache prevents re-generating mesh data for an animated model
3646 * multiple times in one frame for lighting, shadowing, reflections, etc.
3649 void R_AnimCache_Free(void)
3653 void R_AnimCache_ClearCache(void)
3656 entity_render_t *ent;
3658 for (i = 0;i < r_refdef.scene.numentities;i++)
3660 ent = r_refdef.scene.entities[i];
3661 ent->animcache_vertex3f = NULL;
3662 ent->animcache_normal3f = NULL;
3663 ent->animcache_svector3f = NULL;
3664 ent->animcache_tvector3f = NULL;
3668 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3670 dp_model_t *model = ent->model;
3672 // see if it's already cached this frame
3673 if (ent->animcache_vertex3f)
3675 // add normals/tangents if needed
3676 if (wantnormals || wanttangents)
3678 if (ent->animcache_normal3f)
3679 wantnormals = false;
3680 if (ent->animcache_svector3f)
3681 wanttangents = false;
3682 if (wantnormals || wanttangents)
3684 numvertices = model->surfmesh.num_vertices;
3686 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3689 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3690 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3692 if (!r_framedata_failed)
3693 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
3699 // see if this ent is worth caching
3700 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
3702 // get some memory for this entity and generate mesh data
3703 numvertices = model->surfmesh.num_vertices;
3704 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3706 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3709 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3710 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3712 if (!r_framedata_failed)
3713 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
3715 return !r_framedata_failed;
3718 void R_AnimCache_CacheVisibleEntities(void)
3721 qboolean wantnormals = !r_showsurfaces.integer;
3722 qboolean wanttangents = !r_showsurfaces.integer;
3724 switch(vid.renderpath)
3726 case RENDERPATH_GL20:
3728 case RENDERPATH_GL13:
3729 case RENDERPATH_GL11:
3730 wanttangents = false;
3734 // TODO: thread this
3735 // NOTE: R_PrepareRTLights() also caches entities
3737 for (i = 0;i < r_refdef.scene.numentities;i++)
3738 if (r_refdef.viewcache.entityvisible[i])
3739 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3741 if (r_shadows.integer)
3742 for (i = 0;i < r_refdef.scene.numentities;i++)
3743 if (!r_refdef.viewcache.entityvisible[i])
3744 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
3747 //==================================================================================
3749 static void R_View_UpdateEntityLighting (void)
3752 entity_render_t *ent;
3753 vec3_t tempdiffusenormal, avg;
3754 vec_t f, fa, fd, fdd;
3756 for (i = 0;i < r_refdef.scene.numentities;i++)
3758 ent = r_refdef.scene.entities[i];
3760 // skip unseen models
3761 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3765 if (ent->model && ent->model->brush.num_leafs)
3767 // TODO: use modellight for r_ambient settings on world?
3768 VectorSet(ent->modellight_ambient, 0, 0, 0);
3769 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3770 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3774 // fetch the lighting from the worldmodel data
3775 VectorClear(ent->modellight_ambient);
3776 VectorClear(ent->modellight_diffuse);
3777 VectorClear(tempdiffusenormal);
3778 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3781 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3782 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3783 if(ent->flags & RENDER_EQUALIZE)
3785 // first fix up ambient lighting...
3786 if(r_equalize_entities_minambient.value > 0)
3788 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3791 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3792 if(fa < r_equalize_entities_minambient.value * fd)
3795 // fa'/fd' = minambient
3796 // fa'+0.25*fd' = fa+0.25*fd
3798 // fa' = fd' * minambient
3799 // fd'*(0.25+minambient) = fa+0.25*fd
3801 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3802 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3804 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3805 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
3806 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3807 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3812 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3814 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3815 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3818 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3819 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3820 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3826 VectorSet(ent->modellight_ambient, 1, 1, 1);
3828 // move the light direction into modelspace coordinates for lighting code
3829 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3830 if(VectorLength2(ent->modellight_lightdir) == 0)
3831 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3832 VectorNormalize(ent->modellight_lightdir);
3836 #define MAX_LINEOFSIGHTTRACES 64
3838 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3841 vec3_t boxmins, boxmaxs;
3844 dp_model_t *model = r_refdef.scene.worldmodel;
3846 if (!model || !model->brush.TraceLineOfSight)
3849 // expand the box a little
3850 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3851 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3852 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3853 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3854 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3855 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3858 VectorCopy(eye, start);
3859 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3860 if (model->brush.TraceLineOfSight(model, start, end))
3863 // try various random positions
3864 for (i = 0;i < numsamples;i++)
3866 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3867 if (model->brush.TraceLineOfSight(model, start, end))
3875 static void R_View_UpdateEntityVisible (void)
3880 entity_render_t *ent;
3882 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3883 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3885 // worldmodel can check visibility
3886 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3887 for (i = 0;i < r_refdef.scene.numentities;i++)
3889 ent = r_refdef.scene.entities[i];
3890 if (!(ent->flags & renderimask))
3891 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)))
3892 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))
3893 r_refdef.viewcache.entityvisible[i] = true;
3895 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3897 for (i = 0;i < r_refdef.scene.numentities;i++)
3899 ent = r_refdef.scene.entities[i];
3900 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3902 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3904 continue; // temp entities do pvs only
3905 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3906 ent->last_trace_visibility = realtime;
3907 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3908 r_refdef.viewcache.entityvisible[i] = 0;
3915 // no worldmodel or it can't check visibility
3916 for (i = 0;i < r_refdef.scene.numentities;i++)
3918 ent = r_refdef.scene.entities[i];
3919 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));
3924 /// only used if skyrendermasked, and normally returns false
3925 int R_DrawBrushModelsSky (void)
3928 entity_render_t *ent;
3931 for (i = 0;i < r_refdef.scene.numentities;i++)
3933 if (!r_refdef.viewcache.entityvisible[i])
3935 ent = r_refdef.scene.entities[i];
3936 if (!ent->model || !ent->model->DrawSky)
3938 ent->model->DrawSky(ent);
3944 static void R_DrawNoModel(entity_render_t *ent);
3945 static void R_DrawModels(void)
3948 entity_render_t *ent;
3950 for (i = 0;i < r_refdef.scene.numentities;i++)
3952 if (!r_refdef.viewcache.entityvisible[i])
3954 ent = r_refdef.scene.entities[i];
3955 r_refdef.stats.entities++;
3956 if (ent->model && ent->model->Draw != NULL)
3957 ent->model->Draw(ent);
3963 static void R_DrawModelsDepth(void)
3966 entity_render_t *ent;
3968 for (i = 0;i < r_refdef.scene.numentities;i++)
3970 if (!r_refdef.viewcache.entityvisible[i])
3972 ent = r_refdef.scene.entities[i];
3973 if (ent->model && ent->model->DrawDepth != NULL)
3974 ent->model->DrawDepth(ent);
3978 static void R_DrawModelsDebug(void)
3981 entity_render_t *ent;
3983 for (i = 0;i < r_refdef.scene.numentities;i++)
3985 if (!r_refdef.viewcache.entityvisible[i])
3987 ent = r_refdef.scene.entities[i];
3988 if (ent->model && ent->model->DrawDebug != NULL)
3989 ent->model->DrawDebug(ent);
3993 static void R_DrawModelsAddWaterPlanes(void)
3996 entity_render_t *ent;
3998 for (i = 0;i < r_refdef.scene.numentities;i++)
4000 if (!r_refdef.viewcache.entityvisible[i])
4002 ent = r_refdef.scene.entities[i];
4003 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4004 ent->model->DrawAddWaterPlanes(ent);
4008 static void R_View_SetFrustum(void)
4011 double slopex, slopey;
4012 vec3_t forward, left, up, origin;
4014 // we can't trust r_refdef.view.forward and friends in reflected scenes
4015 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4018 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4019 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4020 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4021 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4022 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4023 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4024 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4025 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4026 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4027 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4028 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4029 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4033 zNear = r_refdef.nearclip;
4034 nudge = 1.0 - 1.0 / (1<<23);
4035 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4036 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4037 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4038 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4039 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4040 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4041 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4042 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4048 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4049 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4050 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4051 r_refdef.view.frustum[0].dist = m[15] - m[12];
4053 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4054 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4055 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4056 r_refdef.view.frustum[1].dist = m[15] + m[12];
4058 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4059 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4060 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4061 r_refdef.view.frustum[2].dist = m[15] - m[13];
4063 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4064 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4065 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4066 r_refdef.view.frustum[3].dist = m[15] + m[13];
4068 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4069 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4070 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4071 r_refdef.view.frustum[4].dist = m[15] - m[14];
4073 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4074 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4075 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4076 r_refdef.view.frustum[5].dist = m[15] + m[14];
4079 if (r_refdef.view.useperspective)
4081 slopex = 1.0 / r_refdef.view.frustum_x;
4082 slopey = 1.0 / r_refdef.view.frustum_y;
4083 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4084 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
4085 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
4086 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
4087 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4089 // Leaving those out was a mistake, those were in the old code, and they
4090 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4091 // I couldn't reproduce it after adding those normalizations. --blub
4092 VectorNormalize(r_refdef.view.frustum[0].normal);
4093 VectorNormalize(r_refdef.view.frustum[1].normal);
4094 VectorNormalize(r_refdef.view.frustum[2].normal);
4095 VectorNormalize(r_refdef.view.frustum[3].normal);
4097 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4098 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]);
4099 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]);
4100 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]);
4101 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]);
4103 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4104 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4105 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4106 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4107 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4111 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4112 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4113 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4114 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4115 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4116 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4117 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4118 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4119 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4120 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4122 r_refdef.view.numfrustumplanes = 5;
4124 if (r_refdef.view.useclipplane)
4126 r_refdef.view.numfrustumplanes = 6;
4127 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4130 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4131 PlaneClassify(r_refdef.view.frustum + i);
4133 // LordHavoc: note to all quake engine coders, Quake had a special case
4134 // for 90 degrees which assumed a square view (wrong), so I removed it,
4135 // Quake2 has it disabled as well.
4137 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4138 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4139 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4140 //PlaneClassify(&frustum[0]);
4142 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4143 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4144 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4145 //PlaneClassify(&frustum[1]);
4147 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4148 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4149 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4150 //PlaneClassify(&frustum[2]);
4152 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4153 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4154 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4155 //PlaneClassify(&frustum[3]);
4158 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4159 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4160 //PlaneClassify(&frustum[4]);
4163 void R_View_Update(void)
4165 R_Main_ResizeViewCache();
4166 R_View_SetFrustum();
4167 R_View_WorldVisibility(r_refdef.view.useclipplane);
4168 R_View_UpdateEntityVisible();
4169 R_View_UpdateEntityLighting();
4172 void R_SetupView(qboolean allowwaterclippingplane)
4174 const double *customclipplane = NULL;
4176 if (r_refdef.view.useclipplane && allowwaterclippingplane)
4178 // LordHavoc: couldn't figure out how to make this approach the
4179 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4180 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4181 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4182 dist = r_refdef.view.clipplane.dist;
4183 plane[0] = r_refdef.view.clipplane.normal[0];
4184 plane[1] = r_refdef.view.clipplane.normal[1];
4185 plane[2] = r_refdef.view.clipplane.normal[2];
4187 customclipplane = plane;
4190 if (!r_refdef.view.useperspective)
4191 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);
4192 else if (vid.stencil && r_useinfinitefarclip.integer)
4193 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);
4195 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);
4196 R_SetViewport(&r_refdef.view.viewport);
4199 void R_ResetViewRendering2D(void)
4201 r_viewport_t viewport;
4204 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4205 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);
4206 R_SetViewport(&viewport);
4207 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
4208 GL_Color(1, 1, 1, 1);
4209 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4210 GL_BlendFunc(GL_ONE, GL_ZERO);
4211 GL_AlphaTest(false);
4212 GL_ScissorTest(false);
4213 GL_DepthMask(false);
4214 GL_DepthRange(0, 1);
4215 GL_DepthTest(false);
4216 R_Mesh_Matrix(&identitymatrix);
4217 R_Mesh_ResetTextureState();
4218 GL_PolygonOffset(0, 0);
4219 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4220 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4221 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4222 qglStencilMask(~0);CHECKGLERROR
4223 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4224 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4225 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
4226 R_SetupGenericShader(true);
4229 void R_ResetViewRendering3D(void)
4234 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4235 GL_Color(1, 1, 1, 1);
4236 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4237 GL_BlendFunc(GL_ONE, GL_ZERO);
4238 GL_AlphaTest(false);
4239 GL_ScissorTest(true);
4241 GL_DepthRange(0, 1);
4243 R_Mesh_Matrix(&identitymatrix);
4244 R_Mesh_ResetTextureState();
4245 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4246 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4247 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4248 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4249 qglStencilMask(~0);CHECKGLERROR
4250 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4251 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4252 GL_CullFace(r_refdef.view.cullface_back);
4253 R_SetupGenericShader(true);
4256 void R_RenderScene(void);
4257 void R_RenderWaterPlanes(void);
4259 static void R_Water_StartFrame(void)
4262 int waterwidth, waterheight, texturewidth, textureheight;
4263 r_waterstate_waterplane_t *p;
4265 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
4268 switch(vid.renderpath)
4270 case RENDERPATH_GL20:
4272 case RENDERPATH_GL13:
4273 case RENDERPATH_GL11:
4277 // set waterwidth and waterheight to the water resolution that will be
4278 // used (often less than the screen resolution for faster rendering)
4279 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4280 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4282 // calculate desired texture sizes
4283 // can't use water if the card does not support the texture size
4284 if (!r_water.integer || r_showsurfaces.integer)
4285 texturewidth = textureheight = waterwidth = waterheight = 0;
4286 else if (vid.support.arb_texture_non_power_of_two)
4288 texturewidth = waterwidth;
4289 textureheight = waterheight;
4293 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4294 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4297 // allocate textures as needed
4298 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4300 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4301 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4303 if (p->texture_refraction)
4304 R_FreeTexture(p->texture_refraction);
4305 p->texture_refraction = NULL;
4306 if (p->texture_reflection)
4307 R_FreeTexture(p->texture_reflection);
4308 p->texture_reflection = NULL;
4310 memset(&r_waterstate, 0, sizeof(r_waterstate));
4311 r_waterstate.texturewidth = texturewidth;
4312 r_waterstate.textureheight = textureheight;
4315 if (r_waterstate.texturewidth)
4317 r_waterstate.enabled = true;
4319 // when doing a reduced render (HDR) we want to use a smaller area
4320 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4321 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4323 // set up variables that will be used in shader setup
4324 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4325 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4326 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4327 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4330 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4331 r_waterstate.numwaterplanes = 0;
4334 void R_Water_AddWaterPlane(msurface_t *surface)
4336 int triangleindex, planeindex;
4342 r_waterstate_waterplane_t *p;
4343 texture_t *t = R_GetCurrentTexture(surface->texture);
4344 // just use the first triangle with a valid normal for any decisions
4345 VectorClear(normal);
4346 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4348 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4349 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4350 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4351 TriangleNormal(vert[0], vert[1], vert[2], normal);
4352 if (VectorLength2(normal) >= 0.001)
4356 VectorCopy(normal, plane.normal);
4357 VectorNormalize(plane.normal);
4358 plane.dist = DotProduct(vert[0], plane.normal);
4359 PlaneClassify(&plane);
4360 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4362 // skip backfaces (except if nocullface is set)
4363 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4365 VectorNegate(plane.normal, plane.normal);
4367 PlaneClassify(&plane);
4371 // find a matching plane if there is one
4372 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4373 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4375 if (planeindex >= r_waterstate.maxwaterplanes)
4376 return; // nothing we can do, out of planes
4378 // if this triangle does not fit any known plane rendered this frame, add one
4379 if (planeindex >= r_waterstate.numwaterplanes)
4381 // store the new plane
4382 r_waterstate.numwaterplanes++;
4384 // clear materialflags and pvs
4385 p->materialflags = 0;
4386 p->pvsvalid = false;
4388 // merge this surface's materialflags into the waterplane
4389 p->materialflags |= t->currentmaterialflags;
4390 // merge this surface's PVS into the waterplane
4391 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4392 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4393 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4395 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4400 static void R_Water_ProcessPlanes(void)
4402 r_refdef_view_t originalview;
4403 r_refdef_view_t myview;
4405 r_waterstate_waterplane_t *p;
4407 originalview = r_refdef.view;
4409 // make sure enough textures are allocated
4410 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4412 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4414 if (!p->texture_refraction)
4415 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);
4416 if (!p->texture_refraction)
4420 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4422 if (!p->texture_reflection)
4423 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);
4424 if (!p->texture_reflection)
4430 r_refdef.view = originalview;
4431 r_refdef.view.showdebug = false;
4432 r_refdef.view.width = r_waterstate.waterwidth;
4433 r_refdef.view.height = r_waterstate.waterheight;
4434 r_refdef.view.useclipplane = true;
4435 myview = r_refdef.view;
4436 r_waterstate.renderingscene = true;
4437 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4439 // render the normal view scene and copy into texture
4440 // (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)
4441 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4443 r_refdef.view = myview;
4444 r_refdef.view.clipplane = p->plane;
4445 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4446 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4447 PlaneClassify(&r_refdef.view.clipplane);
4449 R_ResetViewRendering3D();
4450 R_ClearScreen(r_refdef.fogenabled);
4454 // copy view into the screen texture
4455 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4456 GL_ActiveTexture(0);
4458 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
4461 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4463 r_refdef.view = myview;
4464 // render reflected scene and copy into texture
4465 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4466 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4467 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4468 r_refdef.view.clipplane = p->plane;
4469 // reverse the cullface settings for this render
4470 r_refdef.view.cullface_front = GL_FRONT;
4471 r_refdef.view.cullface_back = GL_BACK;
4472 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4474 r_refdef.view.usecustompvs = true;
4476 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4478 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4481 R_ResetViewRendering3D();
4482 R_ClearScreen(r_refdef.fogenabled);
4486 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4487 GL_ActiveTexture(0);
4489 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
4492 r_waterstate.renderingscene = false;
4493 r_refdef.view = originalview;
4494 R_ResetViewRendering3D();
4495 R_ClearScreen(r_refdef.fogenabled);
4499 r_refdef.view = originalview;
4500 r_waterstate.renderingscene = false;
4501 Cvar_SetValueQuick(&r_water, 0);
4502 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4506 void R_Bloom_StartFrame(void)
4508 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4510 switch(vid.renderpath)
4512 case RENDERPATH_GL20:
4514 case RENDERPATH_GL13:
4515 case RENDERPATH_GL11:
4519 // set bloomwidth and bloomheight to the bloom resolution that will be
4520 // used (often less than the screen resolution for faster rendering)
4521 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4522 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4523 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4524 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
4525 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
4527 // calculate desired texture sizes
4528 if (vid.support.arb_texture_non_power_of_two)
4530 screentexturewidth = r_refdef.view.width;
4531 screentextureheight = r_refdef.view.height;
4532 bloomtexturewidth = r_bloomstate.bloomwidth;
4533 bloomtextureheight = r_bloomstate.bloomheight;
4537 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4538 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4539 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4540 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4543 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))
4545 Cvar_SetValueQuick(&r_hdr, 0);
4546 Cvar_SetValueQuick(&r_bloom, 0);
4547 Cvar_SetValueQuick(&r_motionblur, 0);
4548 Cvar_SetValueQuick(&r_damageblur, 0);
4551 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)))
4552 screentexturewidth = screentextureheight = 0;
4553 if (!r_hdr.integer && !r_bloom.integer)
4554 bloomtexturewidth = bloomtextureheight = 0;
4556 // allocate textures as needed
4557 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4559 if (r_bloomstate.texture_screen)
4560 R_FreeTexture(r_bloomstate.texture_screen);
4561 r_bloomstate.texture_screen = NULL;
4562 r_bloomstate.screentexturewidth = screentexturewidth;
4563 r_bloomstate.screentextureheight = screentextureheight;
4564 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4565 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);
4567 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4569 if (r_bloomstate.texture_bloom)
4570 R_FreeTexture(r_bloomstate.texture_bloom);
4571 r_bloomstate.texture_bloom = NULL;
4572 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4573 r_bloomstate.bloomtextureheight = bloomtextureheight;
4574 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4575 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);
4578 // when doing a reduced render (HDR) we want to use a smaller area
4579 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4580 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4581 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4582 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4583 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4585 // set up a texcoord array for the full resolution screen image
4586 // (we have to keep this around to copy back during final render)
4587 r_bloomstate.screentexcoord2f[0] = 0;
4588 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4589 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4590 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4591 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4592 r_bloomstate.screentexcoord2f[5] = 0;
4593 r_bloomstate.screentexcoord2f[6] = 0;
4594 r_bloomstate.screentexcoord2f[7] = 0;
4596 // set up a texcoord array for the reduced resolution bloom image
4597 // (which will be additive blended over the screen image)
4598 r_bloomstate.bloomtexcoord2f[0] = 0;
4599 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4600 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4601 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4602 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4603 r_bloomstate.bloomtexcoord2f[5] = 0;
4604 r_bloomstate.bloomtexcoord2f[6] = 0;
4605 r_bloomstate.bloomtexcoord2f[7] = 0;
4607 if (r_hdr.integer || r_bloom.integer)
4609 r_bloomstate.enabled = true;
4610 r_bloomstate.hdr = r_hdr.integer != 0;
4613 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);
4616 void R_Bloom_CopyBloomTexture(float colorscale)
4618 r_refdef.stats.bloom++;
4620 // scale down screen texture to the bloom texture size
4622 R_SetViewport(&r_bloomstate.viewport);
4623 GL_BlendFunc(GL_ONE, GL_ZERO);
4624 GL_Color(colorscale, colorscale, colorscale, 1);
4625 // TODO: optimize with multitexture or GLSL
4626 R_SetupGenericShader(true);
4627 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4628 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4629 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4630 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4632 // we now have a bloom image in the framebuffer
4633 // copy it into the bloom image texture for later processing
4634 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4635 GL_ActiveTexture(0);
4637 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4638 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4641 void R_Bloom_CopyHDRTexture(void)
4643 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4644 GL_ActiveTexture(0);
4646 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
4647 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4650 void R_Bloom_MakeTexture(void)
4653 float xoffset, yoffset, r, brighten;
4655 r_refdef.stats.bloom++;
4657 R_ResetViewRendering2D();
4658 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4659 R_Mesh_ColorPointer(NULL, 0, 0);
4660 R_SetupGenericShader(true);
4662 // we have a bloom image in the framebuffer
4664 R_SetViewport(&r_bloomstate.viewport);
4666 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4669 r = bound(0, r_bloom_colorexponent.value / x, 1);
4670 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4671 GL_Color(r, r, r, 1);
4672 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4673 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4674 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4675 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4677 // copy the vertically blurred bloom view to a texture
4678 GL_ActiveTexture(0);
4680 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4681 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4684 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4685 brighten = r_bloom_brighten.value;
4687 brighten *= r_hdr_range.value;
4688 brighten = sqrt(brighten);
4690 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4691 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4692 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4694 for (dir = 0;dir < 2;dir++)
4696 // blend on at multiple vertical offsets to achieve a vertical blur
4697 // TODO: do offset blends using GLSL
4698 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4699 GL_BlendFunc(GL_ONE, GL_ZERO);
4700 for (x = -range;x <= range;x++)
4702 if (!dir){xoffset = 0;yoffset = x;}
4703 else {xoffset = x;yoffset = 0;}
4704 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4705 yoffset /= (float)r_bloomstate.bloomtextureheight;
4706 // compute a texcoord array with the specified x and y offset
4707 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4708 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4709 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4710 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4711 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4712 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4713 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4714 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4715 // this r value looks like a 'dot' particle, fading sharply to
4716 // black at the edges
4717 // (probably not realistic but looks good enough)
4718 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4719 //r = brighten/(range*2+1);
4720 r = brighten / (range * 2 + 1);
4722 r *= (1 - x*x/(float)(range*range));
4723 GL_Color(r, r, r, 1);
4724 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4725 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4726 GL_BlendFunc(GL_ONE, GL_ONE);
4729 // copy the vertically blurred bloom view to a texture
4730 GL_ActiveTexture(0);
4732 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4733 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4736 // apply subtract last
4737 // (just like it would be in a GLSL shader)
4738 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
4740 GL_BlendFunc(GL_ONE, GL_ZERO);
4741 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4742 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4743 GL_Color(1, 1, 1, 1);
4744 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4745 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4747 GL_BlendFunc(GL_ONE, GL_ONE);
4748 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4749 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4750 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4751 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4752 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4753 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4754 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4756 // copy the darkened bloom view to a texture
4757 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4758 GL_ActiveTexture(0);
4760 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4761 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4765 void R_HDR_RenderBloomTexture(void)
4767 int oldwidth, oldheight;
4768 float oldcolorscale;
4770 oldcolorscale = r_refdef.view.colorscale;
4771 oldwidth = r_refdef.view.width;
4772 oldheight = r_refdef.view.height;
4773 r_refdef.view.width = r_bloomstate.bloomwidth;
4774 r_refdef.view.height = r_bloomstate.bloomheight;
4776 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4777 // TODO: add exposure compensation features
4778 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4780 r_refdef.view.showdebug = false;
4781 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4783 R_ResetViewRendering3D();
4785 R_ClearScreen(r_refdef.fogenabled);
4786 if (r_timereport_active)
4787 R_TimeReport("HDRclear");
4790 if (r_timereport_active)
4791 R_TimeReport("visibility");
4793 // only do secondary renders with HDR if r_hdr is 2 or higher
4794 r_waterstate.numwaterplanes = 0;
4795 if (r_waterstate.enabled && r_hdr.integer >= 2)
4796 R_RenderWaterPlanes();
4798 r_refdef.view.showdebug = true;
4800 r_waterstate.numwaterplanes = 0;
4802 R_ResetViewRendering2D();
4804 R_Bloom_CopyHDRTexture();
4805 R_Bloom_MakeTexture();
4807 // restore the view settings
4808 r_refdef.view.width = oldwidth;
4809 r_refdef.view.height = oldheight;
4810 r_refdef.view.colorscale = oldcolorscale;
4812 R_ResetViewRendering3D();
4814 R_ClearScreen(r_refdef.fogenabled);
4815 if (r_timereport_active)
4816 R_TimeReport("viewclear");
4819 static void R_BlendView(void)
4821 unsigned int permutation;
4823 switch (vid.renderpath)
4825 case RENDERPATH_GL20:
4827 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4828 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4829 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4830 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4831 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4833 if (r_bloomstate.texture_screen)
4835 // make sure the buffer is available
4836 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4838 R_ResetViewRendering2D();
4839 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4840 R_Mesh_ColorPointer(NULL, 0, 0);
4841 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4842 GL_ActiveTexture(0);CHECKGLERROR
4844 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4846 // declare variables
4848 static float avgspeed;
4850 speed = VectorLength(cl.movement_velocity);
4852 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4853 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4855 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4856 speed = bound(0, speed, 1);
4857 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4859 // calculate values into a standard alpha
4860 cl.motionbluralpha = 1 - exp(-
4862 (r_motionblur.value * speed / 80)
4864 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4867 max(0.0001, cl.time - cl.oldtime) // fps independent
4870 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4871 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4873 if (cl.motionbluralpha > 0)
4875 R_SetupGenericShader(true);
4876 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4877 GL_Color(1, 1, 1, cl.motionbluralpha);
4878 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4879 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4880 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4881 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4885 // copy view into the screen texture
4886 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
4887 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4889 else if (!r_bloomstate.texture_bloom)
4891 // we may still have to do view tint...
4892 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4894 // apply a color tint to the whole view
4895 R_ResetViewRendering2D();
4896 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4897 R_Mesh_ColorPointer(NULL, 0, 0);
4898 R_SetupGenericShader(false);
4899 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4900 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4901 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4903 break; // no screen processing, no bloom, skip it
4906 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4908 // render simple bloom effect
4909 // copy the screen and shrink it and darken it for the bloom process
4910 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4911 // make the bloom texture
4912 R_Bloom_MakeTexture();
4915 R_ResetViewRendering2D();
4916 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4917 R_Mesh_ColorPointer(NULL, 0, 0);
4918 GL_Color(1, 1, 1, 1);
4919 GL_BlendFunc(GL_ONE, GL_ZERO);
4920 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4921 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4922 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4923 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4924 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4925 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4926 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4927 if (r_glsl_permutation->loc_ViewTintColor >= 0)
4928 qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4929 if (r_glsl_permutation->loc_ClientTime >= 0)
4930 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4931 if (r_glsl_permutation->loc_PixelSize >= 0)
4932 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4933 if (r_glsl_permutation->loc_UserVec1 >= 0)
4935 float a=0, b=0, c=0, d=0;
4936 #if _MSC_VER >= 1400
4937 #define sscanf sscanf_s
4939 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4940 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4942 if (r_glsl_permutation->loc_UserVec2 >= 0)
4944 float a=0, b=0, c=0, d=0;
4945 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4946 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4948 if (r_glsl_permutation->loc_UserVec3 >= 0)
4950 float a=0, b=0, c=0, d=0;
4951 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4952 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4954 if (r_glsl_permutation->loc_UserVec4 >= 0)
4956 float a=0, b=0, c=0, d=0;
4957 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4958 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4960 if (r_glsl_permutation->loc_Saturation >= 0)
4961 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4962 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4963 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4965 case RENDERPATH_GL13:
4966 case RENDERPATH_GL11:
4967 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4969 // apply a color tint to the whole view
4970 R_ResetViewRendering2D();
4971 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4972 R_Mesh_ColorPointer(NULL, 0, 0);
4973 R_SetupGenericShader(false);
4974 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4975 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4976 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4982 matrix4x4_t r_waterscrollmatrix;
4984 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4986 if (r_refdef.fog_density)
4988 r_refdef.fogcolor[0] = r_refdef.fog_red;
4989 r_refdef.fogcolor[1] = r_refdef.fog_green;
4990 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4992 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4993 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4994 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4995 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4999 VectorCopy(r_refdef.fogcolor, fogvec);
5000 // color.rgb *= ContrastBoost * SceneBrightness;
5001 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5002 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5003 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5004 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5009 void R_UpdateVariables(void)
5013 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
5015 r_refdef.farclip = r_farclip_base.value;
5016 if (r_refdef.scene.worldmodel)
5017 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5018 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5020 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5021 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5022 r_refdef.polygonfactor = 0;
5023 r_refdef.polygonoffset = 0;
5024 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5025 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5027 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5028 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5029 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5030 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5031 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5032 if (r_showsurfaces.integer)
5034 r_refdef.scene.rtworld = false;
5035 r_refdef.scene.rtworldshadows = false;
5036 r_refdef.scene.rtdlight = false;
5037 r_refdef.scene.rtdlightshadows = false;
5038 r_refdef.lightmapintensity = 0;
5041 if (gamemode == GAME_NEHAHRA)
5043 if (gl_fogenable.integer)
5045 r_refdef.oldgl_fogenable = true;
5046 r_refdef.fog_density = gl_fogdensity.value;
5047 r_refdef.fog_red = gl_fogred.value;
5048 r_refdef.fog_green = gl_foggreen.value;
5049 r_refdef.fog_blue = gl_fogblue.value;
5050 r_refdef.fog_alpha = 1;
5051 r_refdef.fog_start = 0;
5052 r_refdef.fog_end = gl_skyclip.value;
5053 r_refdef.fog_height = 1<<30;
5054 r_refdef.fog_fadedepth = 128;
5056 else if (r_refdef.oldgl_fogenable)
5058 r_refdef.oldgl_fogenable = false;
5059 r_refdef.fog_density = 0;
5060 r_refdef.fog_red = 0;
5061 r_refdef.fog_green = 0;
5062 r_refdef.fog_blue = 0;
5063 r_refdef.fog_alpha = 0;
5064 r_refdef.fog_start = 0;
5065 r_refdef.fog_end = 0;
5066 r_refdef.fog_height = 1<<30;
5067 r_refdef.fog_fadedepth = 128;
5071 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5072 r_refdef.fog_start = max(0, r_refdef.fog_start);
5073 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5075 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5077 if (r_refdef.fog_density && r_drawfog.integer)
5079 r_refdef.fogenabled = true;
5080 // this is the point where the fog reaches 0.9986 alpha, which we
5081 // consider a good enough cutoff point for the texture
5082 // (0.9986 * 256 == 255.6)
5083 if (r_fog_exp2.integer)
5084 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5086 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5087 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5088 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5089 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5090 // fog color was already set
5091 // update the fog texture
5092 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)
5093 R_BuildFogTexture();
5096 r_refdef.fogenabled = false;
5098 switch(vid.renderpath)
5100 case RENDERPATH_GL20:
5101 if(v_glslgamma.integer && !vid_gammatables_trivial)
5103 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5105 // build GLSL gamma texture
5106 #define RAMPWIDTH 256
5107 unsigned short ramp[RAMPWIDTH * 3];
5108 unsigned char rampbgr[RAMPWIDTH][4];
5111 r_texture_gammaramps_serial = vid_gammatables_serial;
5113 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5114 for(i = 0; i < RAMPWIDTH; ++i)
5116 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5117 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5118 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5121 if (r_texture_gammaramps)
5123 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5127 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);
5133 // remove GLSL gamma texture
5136 case RENDERPATH_GL13:
5137 case RENDERPATH_GL11:
5142 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5143 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5149 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5150 if( scenetype != r_currentscenetype ) {
5151 // store the old scenetype
5152 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5153 r_currentscenetype = scenetype;
5154 // move in the new scene
5155 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5164 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5166 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5167 if( scenetype == r_currentscenetype ) {
5168 return &r_refdef.scene;
5170 return &r_scenes_store[ scenetype ];
5179 void R_RenderView(void)
5181 if (r_timereport_active)
5182 R_TimeReport("start");
5183 r_frame++; // used only by R_GetCurrentTexture
5184 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5186 if (!r_drawentities.integer)
5187 r_refdef.scene.numentities = 0;
5189 R_AnimCache_ClearCache();
5190 R_FrameData_NewFrame();
5192 if (r_refdef.view.isoverlay)
5194 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5195 GL_Clear( GL_DEPTH_BUFFER_BIT );
5196 R_TimeReport("depthclear");
5198 r_refdef.view.showdebug = false;
5200 r_waterstate.enabled = false;
5201 r_waterstate.numwaterplanes = 0;
5209 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
5210 return; //Host_Error ("R_RenderView: NULL worldmodel");
5212 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
5214 // break apart the view matrix into vectors for various purposes
5215 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5216 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5217 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5218 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5219 // make an inverted copy of the view matrix for tracking sprites
5220 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5222 R_Shadow_UpdateWorldLightSelection();
5224 R_Bloom_StartFrame();
5225 R_Water_StartFrame();
5228 if (r_timereport_active)
5229 R_TimeReport("viewsetup");
5231 R_ResetViewRendering3D();
5233 if (r_refdef.view.clear || r_refdef.fogenabled)
5235 R_ClearScreen(r_refdef.fogenabled);
5236 if (r_timereport_active)
5237 R_TimeReport("viewclear");
5239 r_refdef.view.clear = true;
5241 // this produces a bloom texture to be used in R_BlendView() later
5242 if (r_hdr.integer && r_bloomstate.bloomwidth)
5243 R_HDR_RenderBloomTexture();
5245 r_refdef.view.showdebug = true;
5248 if (r_timereport_active)
5249 R_TimeReport("visibility");
5251 r_waterstate.numwaterplanes = 0;
5252 if (r_waterstate.enabled)
5253 R_RenderWaterPlanes();
5256 r_waterstate.numwaterplanes = 0;
5259 if (r_timereport_active)
5260 R_TimeReport("blendview");
5262 GL_Scissor(0, 0, vid.width, vid.height);
5263 GL_ScissorTest(false);
5267 void R_RenderWaterPlanes(void)
5269 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5271 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5272 if (r_timereport_active)
5273 R_TimeReport("waterworld");
5276 // don't let sound skip if going slow
5277 if (r_refdef.scene.extraupdate)
5280 R_DrawModelsAddWaterPlanes();
5281 if (r_timereport_active)
5282 R_TimeReport("watermodels");
5284 if (r_waterstate.numwaterplanes)
5286 R_Water_ProcessPlanes();
5287 if (r_timereport_active)
5288 R_TimeReport("waterscenes");
5292 extern void R_DrawLightningBeams (void);
5293 extern void VM_CL_AddPolygonsToMeshQueue (void);
5294 extern void R_DrawPortals (void);
5295 extern cvar_t cl_locs_show;
5296 static void R_DrawLocs(void);
5297 static void R_DrawEntityBBoxes(void);
5298 static void R_DrawModelDecals(void);
5299 extern cvar_t cl_decals_newsystem;
5300 extern qboolean r_shadow_usingdeferredprepass;
5301 void R_RenderScene(void)
5303 r_refdef.stats.renders++;
5307 // don't let sound skip if going slow
5308 if (r_refdef.scene.extraupdate)
5311 R_MeshQueue_BeginScene();
5315 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);
5317 if (cl.csqc_vidvars.drawworld)
5319 // don't let sound skip if going slow
5320 if (r_refdef.scene.extraupdate)
5323 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5325 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5326 if (r_timereport_active)
5327 R_TimeReport("worldsky");
5330 if (R_DrawBrushModelsSky() && r_timereport_active)
5331 R_TimeReport("bmodelsky");
5333 if (skyrendermasked && skyrenderlater)
5335 // we have to force off the water clipping plane while rendering sky
5339 if (r_timereport_active)
5340 R_TimeReport("sky");
5344 R_AnimCache_CacheVisibleEntities();
5345 if (r_timereport_active)
5346 R_TimeReport("animation");
5348 R_Shadow_PrepareLights();
5349 if (r_timereport_active)
5350 R_TimeReport("preparelights");
5352 if (r_shadow_usingdeferredprepass)
5353 R_Shadow_DrawPrepass();
5355 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5357 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5358 if (r_timereport_active)
5359 R_TimeReport("worlddepth");
5361 if (r_depthfirst.integer >= 2)
5363 R_DrawModelsDepth();
5364 if (r_timereport_active)
5365 R_TimeReport("modeldepth");
5368 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5370 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5371 if (r_timereport_active)
5372 R_TimeReport("world");
5375 // don't let sound skip if going slow
5376 if (r_refdef.scene.extraupdate)
5380 if (r_timereport_active)
5381 R_TimeReport("models");
5383 // don't let sound skip if going slow
5384 if (r_refdef.scene.extraupdate)
5387 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5389 R_DrawModelShadows();
5390 R_ResetViewRendering3D();
5391 // don't let sound skip if going slow
5392 if (r_refdef.scene.extraupdate)
5396 if (!r_shadow_usingdeferredprepass)
5398 R_Shadow_DrawLights();
5399 if (r_timereport_active)
5400 R_TimeReport("rtlights");
5403 // don't let sound skip if going slow
5404 if (r_refdef.scene.extraupdate)
5407 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5409 R_DrawModelShadows();
5410 R_ResetViewRendering3D();
5411 // don't let sound skip if going slow
5412 if (r_refdef.scene.extraupdate)
5416 if (cl.csqc_vidvars.drawworld)
5418 if (cl_decals_newsystem.integer)
5420 R_DrawModelDecals();
5421 if (r_timereport_active)
5422 R_TimeReport("modeldecals");
5427 if (r_timereport_active)
5428 R_TimeReport("decals");
5432 if (r_timereport_active)
5433 R_TimeReport("particles");
5436 if (r_timereport_active)
5437 R_TimeReport("explosions");
5439 R_DrawLightningBeams();
5440 if (r_timereport_active)
5441 R_TimeReport("lightning");
5444 R_SetupGenericShader(true);
5445 VM_CL_AddPolygonsToMeshQueue();
5447 if (r_refdef.view.showdebug)
5449 if (cl_locs_show.integer)
5452 if (r_timereport_active)
5453 R_TimeReport("showlocs");
5456 if (r_drawportals.integer)
5459 if (r_timereport_active)
5460 R_TimeReport("portals");
5463 if (r_showbboxes.value > 0)
5465 R_DrawEntityBBoxes();
5466 if (r_timereport_active)
5467 R_TimeReport("bboxes");
5471 R_SetupGenericShader(true);
5472 R_MeshQueue_RenderTransparent();
5473 if (r_timereport_active)
5474 R_TimeReport("drawtrans");
5476 R_SetupGenericShader(true);
5478 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))
5480 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5481 if (r_timereport_active)
5482 R_TimeReport("worlddebug");
5483 R_DrawModelsDebug();
5484 if (r_timereport_active)
5485 R_TimeReport("modeldebug");
5488 R_SetupGenericShader(true);
5490 if (cl.csqc_vidvars.drawworld)
5492 R_Shadow_DrawCoronas();
5493 if (r_timereport_active)
5494 R_TimeReport("coronas");
5497 // don't let sound skip if going slow
5498 if (r_refdef.scene.extraupdate)
5501 R_ResetViewRendering2D();
5504 static const unsigned short bboxelements[36] =
5514 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5517 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5519 RSurf_ActiveWorldEntity();
5521 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5522 GL_DepthMask(false);
5523 GL_DepthRange(0, 1);
5524 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5525 R_Mesh_ResetTextureState();
5527 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5528 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5529 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5530 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5531 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5532 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5533 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5534 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5535 R_FillColors(color4f, 8, cr, cg, cb, ca);
5536 if (r_refdef.fogenabled)
5538 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5540 f1 = RSurf_FogVertex(v);
5542 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5543 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5544 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5547 R_Mesh_VertexPointer(vertex3f, 0, 0);
5548 R_Mesh_ColorPointer(color4f, 0, 0);
5549 R_Mesh_ResetTextureState();
5550 R_SetupGenericShader(false);
5551 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5554 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5558 prvm_edict_t *edict;
5559 prvm_prog_t *prog_save = prog;
5561 // this function draws bounding boxes of server entities
5565 GL_CullFace(GL_NONE);
5566 R_SetupGenericShader(false);
5570 for (i = 0;i < numsurfaces;i++)
5572 edict = PRVM_EDICT_NUM(surfacelist[i]);
5573 switch ((int)edict->fields.server->solid)
5575 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5576 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5577 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5578 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5579 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5580 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5582 color[3] *= r_showbboxes.value;
5583 color[3] = bound(0, color[3], 1);
5584 GL_DepthTest(!r_showdisabledepthtest.integer);
5585 GL_CullFace(r_refdef.view.cullface_front);
5586 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5592 static void R_DrawEntityBBoxes(void)
5595 prvm_edict_t *edict;
5597 prvm_prog_t *prog_save = prog;
5599 // this function draws bounding boxes of server entities
5605 for (i = 0;i < prog->num_edicts;i++)
5607 edict = PRVM_EDICT_NUM(i);
5608 if (edict->priv.server->free)
5610 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5611 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5613 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5615 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5616 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5622 static const int nomodelelement3i[24] =
5634 static const unsigned short nomodelelement3s[24] =
5646 static const float nomodelvertex3f[6*3] =
5656 static const float nomodelcolor4f[6*4] =
5658 0.0f, 0.0f, 0.5f, 1.0f,
5659 0.0f, 0.0f, 0.5f, 1.0f,
5660 0.0f, 0.5f, 0.0f, 1.0f,
5661 0.0f, 0.5f, 0.0f, 1.0f,
5662 0.5f, 0.0f, 0.0f, 1.0f,
5663 0.5f, 0.0f, 0.0f, 1.0f
5666 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5672 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);
5674 // this is only called once per entity so numsurfaces is always 1, and
5675 // surfacelist is always {0}, so this code does not handle batches
5677 if (rsurface.ent_flags & RENDER_ADDITIVE)
5679 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5680 GL_DepthMask(false);
5682 else if (rsurface.colormod[3] < 1)
5684 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5685 GL_DepthMask(false);
5689 GL_BlendFunc(GL_ONE, GL_ZERO);
5692 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5693 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5694 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5695 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5696 R_SetupGenericShader(false);
5697 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5698 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5699 R_Mesh_ColorPointer(color4f, 0, 0);
5700 for (i = 0, c = color4f;i < 6;i++, c += 4)
5702 c[0] *= rsurface.colormod[0];
5703 c[1] *= rsurface.colormod[1];
5704 c[2] *= rsurface.colormod[2];
5705 c[3] *= rsurface.colormod[3];
5707 if (r_refdef.fogenabled)
5709 for (i = 0, c = color4f;i < 6;i++, c += 4)
5711 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5713 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5714 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5715 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5718 R_Mesh_ResetTextureState();
5719 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5722 void R_DrawNoModel(entity_render_t *ent)
5725 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5726 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5727 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5729 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5732 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5734 vec3_t right1, right2, diff, normal;
5736 VectorSubtract (org2, org1, normal);
5738 // calculate 'right' vector for start
5739 VectorSubtract (r_refdef.view.origin, org1, diff);
5740 CrossProduct (normal, diff, right1);
5741 VectorNormalize (right1);
5743 // calculate 'right' vector for end
5744 VectorSubtract (r_refdef.view.origin, org2, diff);
5745 CrossProduct (normal, diff, right2);
5746 VectorNormalize (right2);
5748 vert[ 0] = org1[0] + width * right1[0];
5749 vert[ 1] = org1[1] + width * right1[1];
5750 vert[ 2] = org1[2] + width * right1[2];
5751 vert[ 3] = org1[0] - width * right1[0];
5752 vert[ 4] = org1[1] - width * right1[1];
5753 vert[ 5] = org1[2] - width * right1[2];
5754 vert[ 6] = org2[0] - width * right2[0];
5755 vert[ 7] = org2[1] - width * right2[1];
5756 vert[ 8] = org2[2] - width * right2[2];
5757 vert[ 9] = org2[0] + width * right2[0];
5758 vert[10] = org2[1] + width * right2[1];
5759 vert[11] = org2[2] + width * right2[2];
5762 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)
5764 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5765 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5766 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5767 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5768 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5769 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5770 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5771 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5772 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5773 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5774 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5775 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5778 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5783 VectorSet(v, x, y, z);
5784 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5785 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5787 if (i == mesh->numvertices)
5789 if (mesh->numvertices < mesh->maxvertices)
5791 VectorCopy(v, vertex3f);
5792 mesh->numvertices++;
5794 return mesh->numvertices;
5800 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5804 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5805 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5806 e = mesh->element3i + mesh->numtriangles * 3;
5807 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5809 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5810 if (mesh->numtriangles < mesh->maxtriangles)
5815 mesh->numtriangles++;
5817 element[1] = element[2];
5821 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5825 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5826 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5827 e = mesh->element3i + mesh->numtriangles * 3;
5828 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5830 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5831 if (mesh->numtriangles < mesh->maxtriangles)
5836 mesh->numtriangles++;
5838 element[1] = element[2];
5842 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5843 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5845 int planenum, planenum2;
5848 mplane_t *plane, *plane2;
5850 double temppoints[2][256*3];
5851 // figure out how large a bounding box we need to properly compute this brush
5853 for (w = 0;w < numplanes;w++)
5854 maxdist = max(maxdist, fabs(planes[w].dist));
5855 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5856 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5857 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5861 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5862 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5864 if (planenum2 == planenum)
5866 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);
5869 if (tempnumpoints < 3)
5871 // generate elements forming a triangle fan for this polygon
5872 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5876 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)
5878 texturelayer_t *layer;
5879 layer = t->currentlayers + t->currentnumlayers++;
5881 layer->depthmask = depthmask;
5882 layer->blendfunc1 = blendfunc1;
5883 layer->blendfunc2 = blendfunc2;
5884 layer->texture = texture;
5885 layer->texmatrix = *matrix;
5886 layer->color[0] = r;
5887 layer->color[1] = g;
5888 layer->color[2] = b;
5889 layer->color[3] = a;
5892 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5895 index = parms[2] + r_refdef.scene.time * parms[3];
5896 index -= floor(index);
5900 case Q3WAVEFUNC_NONE:
5901 case Q3WAVEFUNC_NOISE:
5902 case Q3WAVEFUNC_COUNT:
5905 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5906 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5907 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5908 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5909 case Q3WAVEFUNC_TRIANGLE:
5911 f = index - floor(index);
5922 return (float)(parms[0] + parms[1] * f);
5925 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5930 matrix4x4_t matrix, temp;
5931 switch(tcmod->tcmod)
5935 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5936 matrix = r_waterscrollmatrix;
5938 matrix = identitymatrix;
5940 case Q3TCMOD_ENTITYTRANSLATE:
5941 // this is used in Q3 to allow the gamecode to control texcoord
5942 // scrolling on the entity, which is not supported in darkplaces yet.
5943 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5945 case Q3TCMOD_ROTATE:
5946 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5947 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5948 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5951 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5953 case Q3TCMOD_SCROLL:
5954 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5956 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5957 w = (int) tcmod->parms[0];
5958 h = (int) tcmod->parms[1];
5959 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5961 idx = (int) floor(f * w * h);
5962 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5964 case Q3TCMOD_STRETCH:
5965 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5966 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5968 case Q3TCMOD_TRANSFORM:
5969 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5970 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5971 VectorSet(tcmat + 6, 0 , 0 , 1);
5972 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5973 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5975 case Q3TCMOD_TURBULENT:
5976 // this is handled in the RSurf_PrepareVertices function
5977 matrix = identitymatrix;
5981 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5984 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5986 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5987 char name[MAX_QPATH];
5988 skinframe_t *skinframe;
5989 unsigned char pixels[296*194];
5990 strlcpy(cache->name, skinname, sizeof(cache->name));
5991 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5992 if (developer_loading.integer)
5993 Con_Printf("loading %s\n", name);
5994 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5995 if (!skinframe || !skinframe->base)
5998 fs_offset_t filesize;
6000 f = FS_LoadFile(name, tempmempool, true, &filesize);
6003 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
6004 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6008 cache->skinframe = skinframe;
6011 texture_t *R_GetCurrentTexture(texture_t *t)
6014 const entity_render_t *ent = rsurface.entity;
6015 dp_model_t *model = ent->model;
6016 q3shaderinfo_layer_tcmod_t *tcmod;
6018 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
6019 return t->currentframe;
6020 t->update_lastrenderframe = r_frame;
6021 t->update_lastrenderentity = (void *)ent;
6023 // switch to an alternate material if this is a q1bsp animated material
6025 texture_t *texture = t;
6026 int s = rsurface.ent_skinnum;
6027 if ((unsigned int)s >= (unsigned int)model->numskins)
6029 if (model->skinscenes)
6031 if (model->skinscenes[s].framecount > 1)
6032 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6034 s = model->skinscenes[s].firstframe;
6037 t = t + s * model->num_surfaces;
6040 // use an alternate animation if the entity's frame is not 0,
6041 // and only if the texture has an alternate animation
6042 if (rsurface.ent_alttextures && t->anim_total[1])
6043 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6045 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6047 texture->currentframe = t;
6050 // update currentskinframe to be a qw skin or animation frame
6051 if (rsurface.ent_qwskin >= 0)
6053 i = rsurface.ent_qwskin;
6054 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6056 r_qwskincache_size = cl.maxclients;
6058 Mem_Free(r_qwskincache);
6059 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6061 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6062 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6063 t->currentskinframe = r_qwskincache[i].skinframe;
6064 if (t->currentskinframe == NULL)
6065 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6067 else if (t->numskinframes >= 2)
6068 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6069 if (t->backgroundnumskinframes >= 2)
6070 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6072 t->currentmaterialflags = t->basematerialflags;
6073 t->currentalpha = rsurface.colormod[3];
6074 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6075 t->currentalpha *= r_wateralpha.value;
6076 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6077 t->currentalpha *= t->r_water_wateralpha;
6078 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6079 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6080 if (!(rsurface.ent_flags & RENDER_LIGHT))
6081 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6082 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6084 // pick a model lighting mode
6085 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6086 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6088 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6090 if (rsurface.ent_flags & RENDER_ADDITIVE)
6091 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6092 else if (t->currentalpha < 1)
6093 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6094 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6095 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6096 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6097 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6098 if (t->backgroundnumskinframes)
6099 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6100 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6102 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6103 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6106 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6107 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6108 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6110 // there is no tcmod
6111 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6113 t->currenttexmatrix = r_waterscrollmatrix;
6114 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6116 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6118 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6119 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6122 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6123 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6124 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6125 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6127 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6128 if (t->currentskinframe->qpixels)
6129 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6130 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6131 t->glosstexture = r_texture_black;
6132 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6133 t->backgroundglosstexture = r_texture_black;
6134 t->specularpower = r_shadow_glossexponent.value;
6135 // TODO: store reference values for these in the texture?
6136 t->specularscale = 0;
6137 if (r_shadow_gloss.integer > 0)
6139 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6141 if (r_shadow_glossintensity.value > 0)
6143 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6144 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6145 t->specularscale = r_shadow_glossintensity.value;
6148 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6150 t->glosstexture = r_texture_white;
6151 t->backgroundglosstexture = r_texture_white;
6152 t->specularscale = r_shadow_gloss2intensity.value;
6153 t->specularpower = r_shadow_gloss2exponent.value;
6156 t->specularscale *= t->specularscalemod;
6157 t->specularpower *= t->specularpowermod;
6159 // lightmaps mode looks bad with dlights using actual texturing, so turn
6160 // off the colormap and glossmap, but leave the normalmap on as it still
6161 // accurately represents the shading involved
6162 if (gl_lightmaps.integer)
6164 t->basetexture = r_texture_grey128;
6165 t->backgroundbasetexture = NULL;
6166 t->specularscale = 0;
6167 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6170 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
6171 VectorClear(t->dlightcolor);
6172 t->currentnumlayers = 0;
6173 if (t->currentmaterialflags & MATERIALFLAG_WALL)
6175 int blendfunc1, blendfunc2;
6177 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6179 blendfunc1 = GL_SRC_ALPHA;
6180 blendfunc2 = GL_ONE;
6182 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6184 blendfunc1 = GL_SRC_ALPHA;
6185 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6187 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6189 blendfunc1 = t->customblendfunc[0];
6190 blendfunc2 = t->customblendfunc[1];
6194 blendfunc1 = GL_ONE;
6195 blendfunc2 = GL_ZERO;
6197 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
6198 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6200 // fullbright is not affected by r_refdef.lightmapintensity
6201 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]);
6202 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6203 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]);
6204 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6205 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]);
6209 vec3_t ambientcolor;
6211 // set the color tint used for lights affecting this surface
6212 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
6214 // q3bsp has no lightmap updates, so the lightstylevalue that
6215 // would normally be baked into the lightmap must be
6216 // applied to the color
6217 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
6218 if (model->type == mod_brushq3)
6219 colorscale *= r_refdef.scene.rtlightstylevalue[0];
6220 colorscale *= r_refdef.lightmapintensity;
6221 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
6222 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
6223 // basic lit geometry
6224 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]);
6225 // add pants/shirt if needed
6226 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6227 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]);
6228 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6229 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]);
6230 // now add ambient passes if needed
6231 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
6233 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]);
6234 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6235 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]);
6236 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6237 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]);
6240 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
6241 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]);
6242 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
6244 // if this is opaque use alpha blend which will darken the earlier
6247 // if this is an alpha blended material, all the earlier passes
6248 // were darkened by fog already, so we only need to add the fog
6249 // color ontop through the fog mask texture
6251 // if this is an additive blended material, all the earlier passes
6252 // were darkened by fog already, and we should not add fog color
6253 // (because the background was not darkened, there is no fog color
6254 // that was lost behind it).
6255 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]);
6259 return t->currentframe;
6262 rsurfacestate_t rsurface;
6264 void R_Mesh_ResizeArrays(int newvertices)
6267 if (rsurface.array_size >= newvertices)
6269 if (rsurface.array_modelvertex3f)
6270 Mem_Free(rsurface.array_modelvertex3f);
6271 rsurface.array_size = (newvertices + 1023) & ~1023;
6272 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6273 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
6274 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
6275 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
6276 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
6277 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
6278 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6279 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6280 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
6281 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
6282 rsurface.array_color4f = base + rsurface.array_size * 27;
6283 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6286 void RSurf_ActiveWorldEntity(void)
6288 dp_model_t *model = r_refdef.scene.worldmodel;
6289 //if (rsurface.entity == r_refdef.scene.worldentity)
6291 rsurface.entity = r_refdef.scene.worldentity;
6292 rsurface.skeleton = NULL;
6293 rsurface.ent_skinnum = 0;
6294 rsurface.ent_qwskin = -1;
6295 rsurface.ent_shadertime = 0;
6296 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6297 if (rsurface.array_size < model->surfmesh.num_vertices)
6298 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6299 rsurface.matrix = identitymatrix;
6300 rsurface.inversematrix = identitymatrix;
6301 rsurface.matrixscale = 1;
6302 rsurface.inversematrixscale = 1;
6303 R_Mesh_Matrix(&identitymatrix);
6304 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6305 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6306 rsurface.fograngerecip = r_refdef.fograngerecip;
6307 rsurface.fogheightfade = r_refdef.fogheightfade;
6308 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6309 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6310 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6311 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6312 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6313 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6314 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6315 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
6316 rsurface.colormod[3] = 1;
6317 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);
6318 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6319 rsurface.frameblend[0].lerp = 1;
6320 rsurface.ent_alttextures = false;
6321 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6322 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6323 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6324 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6325 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6326 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6327 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6328 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6329 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6330 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6331 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6332 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6333 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6334 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6335 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6336 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6337 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6338 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6339 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6340 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6341 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6342 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6343 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6344 rsurface.modelelement3i = model->surfmesh.data_element3i;
6345 rsurface.modelelement3s = model->surfmesh.data_element3s;
6346 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6347 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6348 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6349 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6350 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6351 rsurface.modelsurfaces = model->data_surfaces;
6352 rsurface.generatedvertex = false;
6353 rsurface.vertex3f = rsurface.modelvertex3f;
6354 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6355 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6356 rsurface.svector3f = rsurface.modelsvector3f;
6357 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6358 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6359 rsurface.tvector3f = rsurface.modeltvector3f;
6360 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6361 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6362 rsurface.normal3f = rsurface.modelnormal3f;
6363 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6364 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6365 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6368 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
6370 dp_model_t *model = ent->model;
6371 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6373 rsurface.entity = (entity_render_t *)ent;
6374 rsurface.skeleton = ent->skeleton;
6375 rsurface.ent_skinnum = ent->skinnum;
6376 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;
6377 rsurface.ent_shadertime = ent->shadertime;
6378 rsurface.ent_flags = ent->flags;
6379 if (rsurface.array_size < model->surfmesh.num_vertices)
6380 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6381 rsurface.matrix = ent->matrix;
6382 rsurface.inversematrix = ent->inversematrix;
6383 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6384 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6385 R_Mesh_Matrix(&rsurface.matrix);
6386 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6387 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6388 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6389 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6390 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6391 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6392 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6393 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6394 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6395 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6396 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6397 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
6398 rsurface.colormod[3] = ent->alpha;
6399 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
6400 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6401 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6402 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6403 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6404 if (ent->model->brush.submodel && !prepass)
6406 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6407 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6409 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6411 if (ent->animcache_vertex3f && !r_framedata_failed)
6413 rsurface.modelvertex3f = ent->animcache_vertex3f;
6414 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
6415 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
6416 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
6418 else if (wanttangents)
6420 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6421 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6422 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6423 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6424 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6426 else if (wantnormals)
6428 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6429 rsurface.modelsvector3f = NULL;
6430 rsurface.modeltvector3f = NULL;
6431 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6432 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6436 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6437 rsurface.modelsvector3f = NULL;
6438 rsurface.modeltvector3f = NULL;
6439 rsurface.modelnormal3f = NULL;
6440 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6442 rsurface.modelvertex3f_bufferobject = 0;
6443 rsurface.modelvertex3f_bufferoffset = 0;
6444 rsurface.modelsvector3f_bufferobject = 0;
6445 rsurface.modelsvector3f_bufferoffset = 0;
6446 rsurface.modeltvector3f_bufferobject = 0;
6447 rsurface.modeltvector3f_bufferoffset = 0;
6448 rsurface.modelnormal3f_bufferobject = 0;
6449 rsurface.modelnormal3f_bufferoffset = 0;
6450 rsurface.generatedvertex = true;
6454 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6455 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6456 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6457 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6458 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6459 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6460 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6461 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6462 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6463 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6464 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6465 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6466 rsurface.generatedvertex = false;
6468 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6469 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6470 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6471 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6472 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6473 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6474 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6475 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6476 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6477 rsurface.modelelement3i = model->surfmesh.data_element3i;
6478 rsurface.modelelement3s = model->surfmesh.data_element3s;
6479 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6480 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6481 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6482 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6483 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6484 rsurface.modelsurfaces = model->data_surfaces;
6485 rsurface.vertex3f = rsurface.modelvertex3f;
6486 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6487 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6488 rsurface.svector3f = rsurface.modelsvector3f;
6489 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6490 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6491 rsurface.tvector3f = rsurface.modeltvector3f;
6492 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6493 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6494 rsurface.normal3f = rsurface.modelnormal3f;
6495 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6496 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6497 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6500 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)
6502 rsurface.entity = r_refdef.scene.worldentity;
6503 rsurface.skeleton = NULL;
6504 rsurface.ent_skinnum = 0;
6505 rsurface.ent_qwskin = -1;
6506 rsurface.ent_shadertime = shadertime;
6507 rsurface.ent_flags = entflags;
6508 rsurface.modelnum_vertices = numvertices;
6509 rsurface.modelnum_triangles = numtriangles;
6510 if (rsurface.array_size < rsurface.modelnum_vertices)
6511 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6512 rsurface.matrix = *matrix;
6513 rsurface.inversematrix = *inversematrix;
6514 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6515 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6516 R_Mesh_Matrix(&rsurface.matrix);
6517 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6518 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6519 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6520 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6521 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6522 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6523 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6524 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6525 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6526 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6527 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6528 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
6529 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);
6530 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6531 rsurface.frameblend[0].lerp = 1;
6532 rsurface.ent_alttextures = false;
6533 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6534 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6537 rsurface.modelvertex3f = vertex3f;
6538 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6539 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6540 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6542 else if (wantnormals)
6544 rsurface.modelvertex3f = vertex3f;
6545 rsurface.modelsvector3f = NULL;
6546 rsurface.modeltvector3f = NULL;
6547 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6551 rsurface.modelvertex3f = vertex3f;
6552 rsurface.modelsvector3f = NULL;
6553 rsurface.modeltvector3f = NULL;
6554 rsurface.modelnormal3f = NULL;
6556 rsurface.modelvertex3f_bufferobject = 0;
6557 rsurface.modelvertex3f_bufferoffset = 0;
6558 rsurface.modelsvector3f_bufferobject = 0;
6559 rsurface.modelsvector3f_bufferoffset = 0;
6560 rsurface.modeltvector3f_bufferobject = 0;
6561 rsurface.modeltvector3f_bufferoffset = 0;
6562 rsurface.modelnormal3f_bufferobject = 0;
6563 rsurface.modelnormal3f_bufferoffset = 0;
6564 rsurface.generatedvertex = true;
6565 rsurface.modellightmapcolor4f = color4f;
6566 rsurface.modellightmapcolor4f_bufferobject = 0;
6567 rsurface.modellightmapcolor4f_bufferoffset = 0;
6568 rsurface.modeltexcoordtexture2f = texcoord2f;
6569 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6570 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6571 rsurface.modeltexcoordlightmap2f = NULL;
6572 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6573 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6574 rsurface.modelelement3i = element3i;
6575 rsurface.modelelement3s = element3s;
6576 rsurface.modelelement3i_bufferobject = 0;
6577 rsurface.modelelement3s_bufferobject = 0;
6578 rsurface.modellightmapoffsets = NULL;
6579 rsurface.modelsurfaces = NULL;
6580 rsurface.vertex3f = rsurface.modelvertex3f;
6581 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6582 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6583 rsurface.svector3f = rsurface.modelsvector3f;
6584 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6585 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6586 rsurface.tvector3f = rsurface.modeltvector3f;
6587 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6588 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6589 rsurface.normal3f = rsurface.modelnormal3f;
6590 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6591 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6592 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6594 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6596 if ((wantnormals || wanttangents) && !normal3f)
6597 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6598 if (wanttangents && !svector3f)
6599 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);
6603 float RSurf_FogPoint(const float *v)
6605 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6606 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6607 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6608 float FogHeightFade = r_refdef.fogheightfade;
6610 unsigned int fogmasktableindex;
6611 if (r_refdef.fogplaneviewabove)
6612 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6614 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6615 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6616 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6619 float RSurf_FogVertex(const float *v)
6621 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6622 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6623 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6624 float FogHeightFade = rsurface.fogheightfade;
6626 unsigned int fogmasktableindex;
6627 if (r_refdef.fogplaneviewabove)
6628 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6630 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6631 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6632 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6635 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6636 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6639 int texturesurfaceindex;
6644 const float *v1, *in_tc;
6646 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6648 q3shaderinfo_deform_t *deform;
6649 // 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
6650 if (rsurface.generatedvertex)
6652 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6653 generatenormals = true;
6654 for (i = 0;i < Q3MAXDEFORMS;i++)
6656 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6658 generatetangents = true;
6659 generatenormals = true;
6661 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6662 generatenormals = true;
6664 if (generatenormals && !rsurface.modelnormal3f)
6666 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6667 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6668 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6669 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6671 if (generatetangents && !rsurface.modelsvector3f)
6673 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6674 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6675 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6676 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6677 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6678 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6679 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);
6682 rsurface.vertex3f = rsurface.modelvertex3f;
6683 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6684 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6685 rsurface.svector3f = rsurface.modelsvector3f;
6686 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6687 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6688 rsurface.tvector3f = rsurface.modeltvector3f;
6689 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6690 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6691 rsurface.normal3f = rsurface.modelnormal3f;
6692 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6693 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6694 // if vertices are deformed (sprite flares and things in maps, possibly
6695 // water waves, bulges and other deformations), generate them into
6696 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6697 // (may be static model data or generated data for an animated model, or
6698 // the previous deform pass)
6699 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6701 switch (deform->deform)
6704 case Q3DEFORM_PROJECTIONSHADOW:
6705 case Q3DEFORM_TEXT0:
6706 case Q3DEFORM_TEXT1:
6707 case Q3DEFORM_TEXT2:
6708 case Q3DEFORM_TEXT3:
6709 case Q3DEFORM_TEXT4:
6710 case Q3DEFORM_TEXT5:
6711 case Q3DEFORM_TEXT6:
6712 case Q3DEFORM_TEXT7:
6715 case Q3DEFORM_AUTOSPRITE:
6716 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6717 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6718 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6719 VectorNormalize(newforward);
6720 VectorNormalize(newright);
6721 VectorNormalize(newup);
6722 // make deformed versions of only the model vertices used by the specified surfaces
6723 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6725 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6726 // a single autosprite surface can contain multiple sprites...
6727 for (j = 0;j < surface->num_vertices - 3;j += 4)
6729 VectorClear(center);
6730 for (i = 0;i < 4;i++)
6731 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6732 VectorScale(center, 0.25f, center);
6733 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6734 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6735 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6736 for (i = 0;i < 4;i++)
6738 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6739 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6742 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);
6743 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);
6745 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6746 rsurface.vertex3f_bufferobject = 0;
6747 rsurface.vertex3f_bufferoffset = 0;
6748 rsurface.svector3f = rsurface.array_deformedsvector3f;
6749 rsurface.svector3f_bufferobject = 0;
6750 rsurface.svector3f_bufferoffset = 0;
6751 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6752 rsurface.tvector3f_bufferobject = 0;
6753 rsurface.tvector3f_bufferoffset = 0;
6754 rsurface.normal3f = rsurface.array_deformednormal3f;
6755 rsurface.normal3f_bufferobject = 0;
6756 rsurface.normal3f_bufferoffset = 0;
6758 case Q3DEFORM_AUTOSPRITE2:
6759 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6760 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6761 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6762 VectorNormalize(newforward);
6763 VectorNormalize(newright);
6764 VectorNormalize(newup);
6765 // make deformed versions of only the model vertices used by the specified surfaces
6766 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6768 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6769 const float *v1, *v2;
6779 memset(shortest, 0, sizeof(shortest));
6780 // a single autosprite surface can contain multiple sprites...
6781 for (j = 0;j < surface->num_vertices - 3;j += 4)
6783 VectorClear(center);
6784 for (i = 0;i < 4;i++)
6785 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6786 VectorScale(center, 0.25f, center);
6787 // find the two shortest edges, then use them to define the
6788 // axis vectors for rotating around the central axis
6789 for (i = 0;i < 6;i++)
6791 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6792 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6794 Debug_PolygonBegin(NULL, 0);
6795 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6796 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);
6797 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6800 l = VectorDistance2(v1, v2);
6801 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6803 l += (1.0f / 1024.0f);
6804 if (shortest[0].length2 > l || i == 0)
6806 shortest[1] = shortest[0];
6807 shortest[0].length2 = l;
6808 shortest[0].v1 = v1;
6809 shortest[0].v2 = v2;
6811 else if (shortest[1].length2 > l || i == 1)
6813 shortest[1].length2 = l;
6814 shortest[1].v1 = v1;
6815 shortest[1].v2 = v2;
6818 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6819 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6821 Debug_PolygonBegin(NULL, 0);
6822 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6823 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);
6824 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6827 // this calculates the right vector from the shortest edge
6828 // and the up vector from the edge midpoints
6829 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6830 VectorNormalize(right);
6831 VectorSubtract(end, start, up);
6832 VectorNormalize(up);
6833 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6834 VectorSubtract(rsurface.localvieworigin, center, forward);
6835 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6836 VectorNegate(forward, forward);
6837 VectorReflect(forward, 0, up, forward);
6838 VectorNormalize(forward);
6839 CrossProduct(up, forward, newright);
6840 VectorNormalize(newright);
6842 Debug_PolygonBegin(NULL, 0);
6843 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);
6844 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6845 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6849 Debug_PolygonBegin(NULL, 0);
6850 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6851 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6852 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6855 // rotate the quad around the up axis vector, this is made
6856 // especially easy by the fact we know the quad is flat,
6857 // so we only have to subtract the center position and
6858 // measure distance along the right vector, and then
6859 // multiply that by the newright vector and add back the
6861 // we also need to subtract the old position to undo the
6862 // displacement from the center, which we do with a
6863 // DotProduct, the subtraction/addition of center is also
6864 // optimized into DotProducts here
6865 l = DotProduct(right, center);
6866 for (i = 0;i < 4;i++)
6868 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6869 f = DotProduct(right, v1) - l;
6870 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6873 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);
6874 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);
6876 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6877 rsurface.vertex3f_bufferobject = 0;
6878 rsurface.vertex3f_bufferoffset = 0;
6879 rsurface.svector3f = rsurface.array_deformedsvector3f;
6880 rsurface.svector3f_bufferobject = 0;
6881 rsurface.svector3f_bufferoffset = 0;
6882 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6883 rsurface.tvector3f_bufferobject = 0;
6884 rsurface.tvector3f_bufferoffset = 0;
6885 rsurface.normal3f = rsurface.array_deformednormal3f;
6886 rsurface.normal3f_bufferobject = 0;
6887 rsurface.normal3f_bufferoffset = 0;
6889 case Q3DEFORM_NORMAL:
6890 // deform the normals to make reflections wavey
6891 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6893 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6894 for (j = 0;j < surface->num_vertices;j++)
6897 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6898 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6899 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6900 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6901 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6902 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6903 VectorNormalize(normal);
6905 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);
6907 rsurface.svector3f = rsurface.array_deformedsvector3f;
6908 rsurface.svector3f_bufferobject = 0;
6909 rsurface.svector3f_bufferoffset = 0;
6910 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6911 rsurface.tvector3f_bufferobject = 0;
6912 rsurface.tvector3f_bufferoffset = 0;
6913 rsurface.normal3f = rsurface.array_deformednormal3f;
6914 rsurface.normal3f_bufferobject = 0;
6915 rsurface.normal3f_bufferoffset = 0;
6918 // deform vertex array to make wavey water and flags and such
6919 waveparms[0] = deform->waveparms[0];
6920 waveparms[1] = deform->waveparms[1];
6921 waveparms[2] = deform->waveparms[2];
6922 waveparms[3] = deform->waveparms[3];
6923 // this is how a divisor of vertex influence on deformation
6924 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6925 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6926 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6928 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6929 for (j = 0;j < surface->num_vertices;j++)
6931 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6932 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6933 // if the wavefunc depends on time, evaluate it per-vertex
6936 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6937 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6939 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6942 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6943 rsurface.vertex3f_bufferobject = 0;
6944 rsurface.vertex3f_bufferoffset = 0;
6946 case Q3DEFORM_BULGE:
6947 // deform vertex array to make the surface have moving bulges
6948 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6950 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6951 for (j = 0;j < surface->num_vertices;j++)
6953 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6954 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6957 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6958 rsurface.vertex3f_bufferobject = 0;
6959 rsurface.vertex3f_bufferoffset = 0;
6962 // deform vertex array
6963 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6964 VectorScale(deform->parms, scale, waveparms);
6965 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6967 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6968 for (j = 0;j < surface->num_vertices;j++)
6969 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6971 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6972 rsurface.vertex3f_bufferobject = 0;
6973 rsurface.vertex3f_bufferoffset = 0;
6977 // generate texcoords based on the chosen texcoord source
6978 switch(rsurface.texture->tcgen.tcgen)
6981 case Q3TCGEN_TEXTURE:
6982 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6983 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6984 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6986 case Q3TCGEN_LIGHTMAP:
6987 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6988 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6989 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6991 case Q3TCGEN_VECTOR:
6992 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6994 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6995 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)
6997 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6998 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
7001 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7002 rsurface.texcoordtexture2f_bufferobject = 0;
7003 rsurface.texcoordtexture2f_bufferoffset = 0;
7005 case Q3TCGEN_ENVIRONMENT:
7006 // make environment reflections using a spheremap
7007 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7009 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7010 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
7011 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
7012 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
7013 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
7015 // identical to Q3A's method, but executed in worldspace so
7016 // carried models can be shiny too
7018 float viewer[3], d, reflected[3], worldreflected[3];
7020 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
7021 // VectorNormalize(viewer);
7023 d = DotProduct(normal, viewer);
7025 reflected[0] = normal[0]*2*d - viewer[0];
7026 reflected[1] = normal[1]*2*d - viewer[1];
7027 reflected[2] = normal[2]*2*d - viewer[2];
7028 // note: this is proportinal to viewer, so we can normalize later
7030 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7031 VectorNormalize(worldreflected);
7033 // note: this sphere map only uses world x and z!
7034 // so positive and negative y will LOOK THE SAME.
7035 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7036 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7039 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7040 rsurface.texcoordtexture2f_bufferobject = 0;
7041 rsurface.texcoordtexture2f_bufferoffset = 0;
7044 // the only tcmod that needs software vertex processing is turbulent, so
7045 // check for it here and apply the changes if needed
7046 // and we only support that as the first one
7047 // (handling a mixture of turbulent and other tcmods would be problematic
7048 // without punting it entirely to a software path)
7049 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7051 amplitude = rsurface.texture->tcmods[0].parms[1];
7052 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7053 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7055 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7056 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)
7058 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7059 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7062 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7063 rsurface.texcoordtexture2f_bufferobject = 0;
7064 rsurface.texcoordtexture2f_bufferoffset = 0;
7066 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7067 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7068 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7069 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7072 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7075 const msurface_t *surface = texturesurfacelist[0];
7076 const msurface_t *surface2;
7081 // TODO: lock all array ranges before render, rather than on each surface
7082 if (texturenumsurfaces == 1)
7084 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7085 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);
7087 else if (r_batchmode.integer == 2)
7089 #define MAXBATCHTRIANGLES 4096
7090 int batchtriangles = 0;
7091 int batchelements[MAXBATCHTRIANGLES*3];
7092 for (i = 0;i < texturenumsurfaces;i = j)
7094 surface = texturesurfacelist[i];
7096 if (surface->num_triangles > MAXBATCHTRIANGLES)
7098 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);
7101 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7102 batchtriangles = surface->num_triangles;
7103 firstvertex = surface->num_firstvertex;
7104 endvertex = surface->num_firstvertex + surface->num_vertices;
7105 for (;j < texturenumsurfaces;j++)
7107 surface2 = texturesurfacelist[j];
7108 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7110 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7111 batchtriangles += surface2->num_triangles;
7112 firstvertex = min(firstvertex, surface2->num_firstvertex);
7113 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7115 surface2 = texturesurfacelist[j-1];
7116 numvertices = endvertex - firstvertex;
7117 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7120 else if (r_batchmode.integer == 1)
7122 for (i = 0;i < texturenumsurfaces;i = j)
7124 surface = texturesurfacelist[i];
7125 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7126 if (texturesurfacelist[j] != surface2)
7128 surface2 = texturesurfacelist[j-1];
7129 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7130 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7131 GL_LockArrays(surface->num_firstvertex, numvertices);
7132 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7137 for (i = 0;i < texturenumsurfaces;i++)
7139 surface = texturesurfacelist[i];
7140 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7141 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);
7146 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
7148 int i, planeindex, vertexindex;
7152 r_waterstate_waterplane_t *p, *bestp;
7153 const msurface_t *surface;
7154 if (r_waterstate.renderingscene)
7156 for (i = 0;i < texturenumsurfaces;i++)
7158 surface = texturesurfacelist[i];
7159 if (lightmaptexunit >= 0)
7160 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7161 if (deluxemaptexunit >= 0)
7162 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7163 // pick the closest matching water plane
7166 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7169 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7171 Matrix4x4_Transform(&rsurface.matrix, v, vert);
7172 d += fabs(PlaneDiff(vert, &p->plane));
7174 if (bestd > d || !bestp)
7182 if (refractiontexunit >= 0)
7183 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
7184 if (reflectiontexunit >= 0)
7185 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
7189 if (refractiontexunit >= 0)
7190 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
7191 if (reflectiontexunit >= 0)
7192 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
7194 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7195 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);
7199 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
7203 const msurface_t *surface = texturesurfacelist[0];
7204 const msurface_t *surface2;
7209 // TODO: lock all array ranges before render, rather than on each surface
7210 if (texturenumsurfaces == 1)
7212 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7213 if (deluxemaptexunit >= 0)
7214 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7215 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7216 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);
7218 else if (r_batchmode.integer == 2)
7220 #define MAXBATCHTRIANGLES 4096
7221 int batchtriangles = 0;
7222 int batchelements[MAXBATCHTRIANGLES*3];
7223 for (i = 0;i < texturenumsurfaces;i = j)
7225 surface = texturesurfacelist[i];
7226 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7227 if (deluxemaptexunit >= 0)
7228 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7230 if (surface->num_triangles > MAXBATCHTRIANGLES)
7232 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);
7235 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7236 batchtriangles = surface->num_triangles;
7237 firstvertex = surface->num_firstvertex;
7238 endvertex = surface->num_firstvertex + surface->num_vertices;
7239 for (;j < texturenumsurfaces;j++)
7241 surface2 = texturesurfacelist[j];
7242 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7244 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7245 batchtriangles += surface2->num_triangles;
7246 firstvertex = min(firstvertex, surface2->num_firstvertex);
7247 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7249 surface2 = texturesurfacelist[j-1];
7250 numvertices = endvertex - firstvertex;
7251 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7254 else if (r_batchmode.integer == 1)
7257 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
7258 for (i = 0;i < texturenumsurfaces;i = j)
7260 surface = texturesurfacelist[i];
7261 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7262 if (texturesurfacelist[j] != surface2)
7264 Con_Printf(" %i", j - i);
7267 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
7269 for (i = 0;i < texturenumsurfaces;i = j)
7271 surface = texturesurfacelist[i];
7272 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7273 if (deluxemaptexunit >= 0)
7274 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7275 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7276 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7279 Con_Printf(" %i", j - i);
7281 surface2 = texturesurfacelist[j-1];
7282 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7283 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7284 GL_LockArrays(surface->num_firstvertex, numvertices);
7285 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7293 for (i = 0;i < texturenumsurfaces;i++)
7295 surface = texturesurfacelist[i];
7296 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7297 if (deluxemaptexunit >= 0)
7298 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7299 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7300 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);
7305 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7308 int texturesurfaceindex;
7309 if (r_showsurfaces.integer == 2)
7311 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7313 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7314 for (j = 0;j < surface->num_triangles;j++)
7316 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7317 GL_Color(f, f, f, 1);
7318 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7324 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7326 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7327 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7328 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);
7329 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7330 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);
7335 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7337 int texturesurfaceindex;
7341 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7343 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7344 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)
7352 rsurface.lightmapcolor4f = rsurface.array_color4f;
7353 rsurface.lightmapcolor4f_bufferobject = 0;
7354 rsurface.lightmapcolor4f_bufferoffset = 0;
7357 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7359 int texturesurfaceindex;
7365 if (rsurface.lightmapcolor4f)
7367 // generate color arrays for the surfaces in this list
7368 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7370 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7371 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)
7373 f = RSurf_FogVertex(v);
7383 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7385 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7386 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)
7388 f = RSurf_FogVertex(v);
7396 rsurface.lightmapcolor4f = rsurface.array_color4f;
7397 rsurface.lightmapcolor4f_bufferobject = 0;
7398 rsurface.lightmapcolor4f_bufferoffset = 0;
7401 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7403 int texturesurfaceindex;
7409 if (!rsurface.lightmapcolor4f)
7411 // generate color arrays for the surfaces in this list
7412 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7414 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7415 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)
7417 f = RSurf_FogVertex(v);
7418 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7419 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7420 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7424 rsurface.lightmapcolor4f = rsurface.array_color4f;
7425 rsurface.lightmapcolor4f_bufferobject = 0;
7426 rsurface.lightmapcolor4f_bufferoffset = 0;
7429 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7431 int texturesurfaceindex;
7435 if (!rsurface.lightmapcolor4f)
7437 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7439 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7440 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)
7448 rsurface.lightmapcolor4f = rsurface.array_color4f;
7449 rsurface.lightmapcolor4f_bufferobject = 0;
7450 rsurface.lightmapcolor4f_bufferoffset = 0;
7453 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7455 int texturesurfaceindex;
7459 if (!rsurface.lightmapcolor4f)
7461 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7463 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7464 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)
7466 c2[0] = c[0] + r_refdef.scene.ambient;
7467 c2[1] = c[1] + r_refdef.scene.ambient;
7468 c2[2] = c[2] + r_refdef.scene.ambient;
7472 rsurface.lightmapcolor4f = rsurface.array_color4f;
7473 rsurface.lightmapcolor4f_bufferobject = 0;
7474 rsurface.lightmapcolor4f_bufferoffset = 0;
7477 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7480 rsurface.lightmapcolor4f = NULL;
7481 rsurface.lightmapcolor4f_bufferobject = 0;
7482 rsurface.lightmapcolor4f_bufferoffset = 0;
7483 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7484 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7485 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7486 GL_Color(r, g, b, a);
7487 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7490 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7492 // TODO: optimize applyfog && applycolor case
7493 // just apply fog if necessary, and tint the fog color array if necessary
7494 rsurface.lightmapcolor4f = NULL;
7495 rsurface.lightmapcolor4f_bufferobject = 0;
7496 rsurface.lightmapcolor4f_bufferoffset = 0;
7497 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7498 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7499 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7500 GL_Color(r, g, b, a);
7501 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7504 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7506 int texturesurfaceindex;
7510 if (texturesurfacelist[0]->lightmapinfo)
7512 // generate color arrays for the surfaces in this list
7513 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7515 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7516 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7518 if (surface->lightmapinfo->samples)
7520 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7521 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7522 VectorScale(lm, scale, c);
7523 if (surface->lightmapinfo->styles[1] != 255)
7525 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7527 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7528 VectorMA(c, scale, lm, c);
7529 if (surface->lightmapinfo->styles[2] != 255)
7532 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7533 VectorMA(c, scale, lm, c);
7534 if (surface->lightmapinfo->styles[3] != 255)
7537 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7538 VectorMA(c, scale, lm, c);
7548 rsurface.lightmapcolor4f = rsurface.array_color4f;
7549 rsurface.lightmapcolor4f_bufferobject = 0;
7550 rsurface.lightmapcolor4f_bufferoffset = 0;
7554 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7555 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7556 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7558 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7559 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7560 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7561 GL_Color(r, g, b, a);
7562 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7565 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7567 int texturesurfaceindex;
7574 vec3_t ambientcolor;
7575 vec3_t diffusecolor;
7579 VectorCopy(rsurface.modellight_lightdir, lightdir);
7580 f = 0.5f * r_refdef.lightmapintensity;
7581 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7582 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7583 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7584 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7585 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7586 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7588 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7590 // generate color arrays for the surfaces in this list
7591 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7593 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7594 int numverts = surface->num_vertices;
7595 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7596 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7597 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7598 // q3-style directional shading
7599 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7601 if ((f = DotProduct(n, lightdir)) > 0)
7602 VectorMA(ambientcolor, f, diffusecolor, c);
7604 VectorCopy(ambientcolor, c);
7612 rsurface.lightmapcolor4f = rsurface.array_color4f;
7613 rsurface.lightmapcolor4f_bufferobject = 0;
7614 rsurface.lightmapcolor4f_bufferoffset = 0;
7615 *applycolor = false;
7619 *r = ambientcolor[0];
7620 *g = ambientcolor[1];
7621 *b = ambientcolor[2];
7622 rsurface.lightmapcolor4f = NULL;
7623 rsurface.lightmapcolor4f_bufferobject = 0;
7624 rsurface.lightmapcolor4f_bufferoffset = 0;
7628 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7630 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7631 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7632 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7633 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7634 GL_Color(r, g, b, a);
7635 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7638 void RSurf_SetupDepthAndCulling(void)
7640 // submodels are biased to avoid z-fighting with world surfaces that they
7641 // may be exactly overlapping (avoids z-fighting artifacts on certain
7642 // doors and things in Quake maps)
7643 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7644 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7645 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7646 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7649 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7651 // transparent sky would be ridiculous
7652 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7654 R_SetupGenericShader(false);
7655 skyrenderlater = true;
7656 RSurf_SetupDepthAndCulling();
7658 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7659 // skymasking on them, and Quake3 never did sky masking (unlike
7660 // software Quake and software Quake2), so disable the sky masking
7661 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7662 // and skymasking also looks very bad when noclipping outside the
7663 // level, so don't use it then either.
7664 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7666 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7667 R_Mesh_ColorPointer(NULL, 0, 0);
7668 R_Mesh_ResetTextureState();
7669 if (skyrendermasked)
7671 R_SetupDepthOrShadowShader();
7672 // depth-only (masking)
7673 GL_ColorMask(0,0,0,0);
7674 // just to make sure that braindead drivers don't draw
7675 // anything despite that colormask...
7676 GL_BlendFunc(GL_ZERO, GL_ONE);
7680 R_SetupGenericShader(false);
7682 GL_BlendFunc(GL_ONE, GL_ZERO);
7684 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7685 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7686 if (skyrendermasked)
7687 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7689 R_Mesh_ResetTextureState();
7690 GL_Color(1, 1, 1, 1);
7693 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
7694 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
7695 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
7697 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7700 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7701 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7702 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7703 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7704 if (rsurface.texture->backgroundcurrentskinframe)
7706 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7707 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7708 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7709 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7711 if (rsurface.texture->colormapping)
7713 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7714 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7716 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7717 if (r_shadow_usingdeferredprepass)
7719 R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture));
7720 R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture));
7722 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7723 R_Mesh_ColorPointer(NULL, 0, 0);
7725 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7727 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass)
7729 // render background
7730 GL_BlendFunc(GL_ONE, GL_ZERO);
7732 GL_AlphaTest(false);
7734 GL_Color(1, 1, 1, 1);
7735 R_Mesh_ColorPointer(NULL, 0, 0);
7737 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7738 if (r_glsl_permutation)
7740 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7741 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7742 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7743 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7744 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7745 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7746 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);
7748 GL_LockArrays(0, 0);
7750 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7751 GL_DepthMask(false);
7752 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7753 R_Mesh_ColorPointer(NULL, 0, 0);
7755 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7756 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7757 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7760 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
7761 if (!r_glsl_permutation)
7764 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7765 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7766 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7767 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7768 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7770 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7772 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7774 GL_BlendFunc(GL_ONE, GL_ZERO);
7776 GL_AlphaTest(false);
7780 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7781 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7782 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
7785 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7787 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7788 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);
7790 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7794 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7795 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);
7797 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7799 GL_LockArrays(0, 0);
7802 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7804 // OpenGL 1.3 path - anything not completely ancient
7805 int texturesurfaceindex;
7806 qboolean applycolor;
7809 const texturelayer_t *layer;
7810 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7812 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7815 int layertexrgbscale;
7816 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7818 if (layerindex == 0)
7822 GL_AlphaTest(false);
7823 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7826 GL_DepthMask(layer->depthmask && writedepth);
7827 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7828 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7830 layertexrgbscale = 4;
7831 VectorScale(layer->color, 0.25f, layercolor);
7833 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7835 layertexrgbscale = 2;
7836 VectorScale(layer->color, 0.5f, layercolor);
7840 layertexrgbscale = 1;
7841 VectorScale(layer->color, 1.0f, layercolor);
7843 layercolor[3] = layer->color[3];
7844 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7845 R_Mesh_ColorPointer(NULL, 0, 0);
7846 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
7847 switch (layer->type)
7849 case TEXTURELAYERTYPE_LITTEXTURE:
7850 // single-pass lightmapped texture with 2x rgbscale
7851 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
7852 R_Mesh_TexMatrix(0, NULL);
7853 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7854 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7855 R_Mesh_TexBind(1, R_GetTexture(layer->texture));
7856 R_Mesh_TexMatrix(1, &layer->texmatrix);
7857 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7858 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7859 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7860 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7861 else if (rsurface.uselightmaptexture)
7862 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7864 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7866 case TEXTURELAYERTYPE_TEXTURE:
7867 // singletexture unlit texture with transparency support
7868 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7869 R_Mesh_TexMatrix(0, &layer->texmatrix);
7870 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7871 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7872 R_Mesh_TexBind(1, 0);
7873 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
7874 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7876 case TEXTURELAYERTYPE_FOG:
7877 // singletexture fogging
7880 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7881 R_Mesh_TexMatrix(0, &layer->texmatrix);
7882 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7883 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7887 R_Mesh_TexBind(0, 0);
7888 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
7890 R_Mesh_TexBind(1, 0);
7891 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
7892 // generate a color array for the fog pass
7893 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7894 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7900 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7901 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)
7903 f = 1 - RSurf_FogVertex(v);
7904 c[0] = layercolor[0];
7905 c[1] = layercolor[1];
7906 c[2] = layercolor[2];
7907 c[3] = f * layercolor[3];
7910 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7913 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7915 GL_LockArrays(0, 0);
7918 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7920 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7921 GL_AlphaTest(false);
7925 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7927 // OpenGL 1.1 - crusty old voodoo path
7928 int texturesurfaceindex;
7931 const texturelayer_t *layer;
7932 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7934 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7936 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7938 if (layerindex == 0)
7942 GL_AlphaTest(false);
7943 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7946 GL_DepthMask(layer->depthmask && writedepth);
7947 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7948 R_Mesh_ColorPointer(NULL, 0, 0);
7949 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
7950 switch (layer->type)
7952 case TEXTURELAYERTYPE_LITTEXTURE:
7953 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7955 // two-pass lit texture with 2x rgbscale
7956 // first the lightmap pass
7957 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
7958 R_Mesh_TexMatrix(0, NULL);
7959 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7960 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7961 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7962 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7963 else if (rsurface.uselightmaptexture)
7964 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7966 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7967 GL_LockArrays(0, 0);
7968 // then apply the texture to it
7969 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7970 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7971 R_Mesh_TexMatrix(0, &layer->texmatrix);
7972 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7973 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7974 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);
7978 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7979 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7980 R_Mesh_TexMatrix(0, &layer->texmatrix);
7981 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7982 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7983 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7984 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);
7986 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);
7989 case TEXTURELAYERTYPE_TEXTURE:
7990 // singletexture unlit texture with transparency support
7991 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7992 R_Mesh_TexMatrix(0, &layer->texmatrix);
7993 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7994 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7995 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);
7997 case TEXTURELAYERTYPE_FOG:
7998 // singletexture fogging
8001 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8002 R_Mesh_TexMatrix(0, &layer->texmatrix);
8003 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8004 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8008 R_Mesh_TexBind(0, 0);
8009 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8011 // generate a color array for the fog pass
8012 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8013 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8019 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8020 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)
8022 f = 1 - RSurf_FogVertex(v);
8023 c[0] = layer->color[0];
8024 c[1] = layer->color[1];
8025 c[2] = layer->color[2];
8026 c[3] = f * layer->color[3];
8029 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8032 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8034 GL_LockArrays(0, 0);
8037 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8039 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8040 GL_AlphaTest(false);
8044 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8048 GL_AlphaTest(false);
8049 R_Mesh_ColorPointer(NULL, 0, 0);
8050 R_Mesh_ResetTextureState();
8051 R_SetupGenericShader(false);
8053 if(rsurface.texture && rsurface.texture->currentskinframe)
8055 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8056 c[3] *= rsurface.texture->currentalpha;
8066 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
8068 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8069 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8070 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8073 // brighten it up (as texture value 127 means "unlit")
8074 c[0] *= 2 * r_refdef.view.colorscale;
8075 c[1] *= 2 * r_refdef.view.colorscale;
8076 c[2] *= 2 * r_refdef.view.colorscale;
8078 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8079 c[3] *= r_wateralpha.value;
8081 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8083 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8084 GL_DepthMask(false);
8086 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8088 GL_BlendFunc(GL_ONE, GL_ONE);
8089 GL_DepthMask(false);
8091 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8093 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8094 GL_DepthMask(false);
8096 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8098 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8099 GL_DepthMask(false);
8103 GL_BlendFunc(GL_ONE, GL_ZERO);
8104 GL_DepthMask(writedepth);
8107 rsurface.lightmapcolor4f = NULL;
8109 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8111 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8113 rsurface.lightmapcolor4f = NULL;
8114 rsurface.lightmapcolor4f_bufferobject = 0;
8115 rsurface.lightmapcolor4f_bufferoffset = 0;
8117 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8119 qboolean applycolor = true;
8122 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8124 r_refdef.lightmapintensity = 1;
8125 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8126 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8130 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8132 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8133 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8134 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8137 if(!rsurface.lightmapcolor4f)
8138 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8140 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8141 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8142 if(r_refdef.fogenabled)
8143 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8145 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8146 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8149 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8152 RSurf_SetupDepthAndCulling();
8153 if (r_showsurfaces.integer == 3 && !prepass)
8155 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8158 switch (vid.renderpath)
8160 case RENDERPATH_GL20:
8161 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8163 case RENDERPATH_GL13:
8164 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8166 case RENDERPATH_GL11:
8167 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8173 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8176 RSurf_SetupDepthAndCulling();
8177 if (r_showsurfaces.integer == 3 && !prepass)
8179 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8182 switch (vid.renderpath)
8184 case RENDERPATH_GL20:
8185 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8187 case RENDERPATH_GL13:
8188 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8190 case RENDERPATH_GL11:
8191 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8197 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8200 int texturenumsurfaces, endsurface;
8202 const msurface_t *surface;
8203 const msurface_t *texturesurfacelist[1024];
8205 // if the model is static it doesn't matter what value we give for
8206 // wantnormals and wanttangents, so this logic uses only rules applicable
8207 // to a model, knowing that they are meaningless otherwise
8208 if (ent == r_refdef.scene.worldentity)
8209 RSurf_ActiveWorldEntity();
8210 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8211 RSurf_ActiveModelEntity(ent, false, false, false);
8214 switch (vid.renderpath)
8216 case RENDERPATH_GL20:
8217 RSurf_ActiveModelEntity(ent, true, true, false);
8219 case RENDERPATH_GL13:
8220 case RENDERPATH_GL11:
8221 RSurf_ActiveModelEntity(ent, true, false, false);
8226 if (r_transparentdepthmasking.integer)
8228 qboolean setup = false;
8229 for (i = 0;i < numsurfaces;i = j)
8232 surface = rsurface.modelsurfaces + surfacelist[i];
8233 texture = surface->texture;
8234 rsurface.texture = R_GetCurrentTexture(texture);
8235 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8236 // scan ahead until we find a different texture
8237 endsurface = min(i + 1024, numsurfaces);
8238 texturenumsurfaces = 0;
8239 texturesurfacelist[texturenumsurfaces++] = surface;
8240 for (;j < endsurface;j++)
8242 surface = rsurface.modelsurfaces + surfacelist[j];
8243 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8245 texturesurfacelist[texturenumsurfaces++] = surface;
8247 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
8249 // render the range of surfaces as depth
8253 GL_ColorMask(0,0,0,0);
8256 GL_BlendFunc(GL_ONE, GL_ZERO);
8258 GL_AlphaTest(false);
8259 R_Mesh_ColorPointer(NULL, 0, 0);
8260 R_Mesh_ResetTextureState();
8261 R_SetupDepthOrShadowShader();
8263 RSurf_SetupDepthAndCulling();
8264 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8265 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8268 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8271 for (i = 0;i < numsurfaces;i = j)
8274 surface = rsurface.modelsurfaces + surfacelist[i];
8275 texture = surface->texture;
8276 rsurface.texture = R_GetCurrentTexture(texture);
8277 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8278 // scan ahead until we find a different texture
8279 endsurface = min(i + 1024, numsurfaces);
8280 texturenumsurfaces = 0;
8281 texturesurfacelist[texturenumsurfaces++] = surface;
8282 for (;j < endsurface;j++)
8284 surface = rsurface.modelsurfaces + surfacelist[j];
8285 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8287 texturesurfacelist[texturenumsurfaces++] = surface;
8289 // render the range of surfaces
8290 if (ent == r_refdef.scene.worldentity)
8291 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8293 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8295 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8296 GL_AlphaTest(false);
8299 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
8301 // transparent surfaces get pushed off into the transparent queue
8302 int surfacelistindex;
8303 const msurface_t *surface;
8304 vec3_t tempcenter, center;
8305 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8307 surface = texturesurfacelist[surfacelistindex];
8308 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8309 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8310 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8311 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8312 if (queueentity->transparent_offset) // transparent offset
8314 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8315 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8316 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8318 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8322 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
8324 const entity_render_t *queueentity = r_refdef.scene.worldentity;
8328 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8330 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8332 RSurf_SetupDepthAndCulling();
8333 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8334 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8338 if (!rsurface.texture->currentnumlayers)
8340 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8341 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8343 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8345 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
8347 RSurf_SetupDepthAndCulling();
8348 GL_AlphaTest(false);
8349 R_Mesh_ColorPointer(NULL, 0, 0);
8350 R_Mesh_ResetTextureState();
8351 R_SetupGenericShader(false);
8352 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8354 GL_BlendFunc(GL_ONE, GL_ZERO);
8355 GL_Color(0, 0, 0, 1);
8356 GL_DepthTest(writedepth);
8357 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8359 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
8361 RSurf_SetupDepthAndCulling();
8362 GL_AlphaTest(false);
8363 R_Mesh_ColorPointer(NULL, 0, 0);
8364 R_Mesh_ResetTextureState();
8365 R_SetupGenericShader(false);
8366 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8368 GL_BlendFunc(GL_ONE, GL_ZERO);
8370 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8372 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8373 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8374 else if (!rsurface.texture->currentnumlayers)
8376 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8378 // in the deferred case, transparent surfaces were queued during prepass
8379 if (!r_shadow_usingdeferredprepass)
8380 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8384 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8385 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8390 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8394 // break the surface list down into batches by texture and use of lightmapping
8395 for (i = 0;i < numsurfaces;i = j)
8398 // texture is the base texture pointer, rsurface.texture is the
8399 // current frame/skin the texture is directing us to use (for example
8400 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8401 // use skin 1 instead)
8402 texture = surfacelist[i]->texture;
8403 rsurface.texture = R_GetCurrentTexture(texture);
8404 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8405 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8407 // if this texture is not the kind we want, skip ahead to the next one
8408 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8412 // simply scan ahead until we find a different texture or lightmap state
8413 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8415 // render the range of surfaces
8416 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
8420 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
8425 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8427 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8429 RSurf_SetupDepthAndCulling();
8430 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8431 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8435 if (!rsurface.texture->currentnumlayers)
8437 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8438 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8440 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8442 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8444 RSurf_SetupDepthAndCulling();
8445 GL_AlphaTest(false);
8446 R_Mesh_ColorPointer(NULL, 0, 0);
8447 R_Mesh_ResetTextureState();
8448 R_SetupGenericShader(false);
8449 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8451 GL_BlendFunc(GL_ONE, GL_ZERO);
8452 GL_Color(0, 0, 0, 1);
8453 GL_DepthTest(writedepth);
8454 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8456 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8458 RSurf_SetupDepthAndCulling();
8459 GL_AlphaTest(false);
8460 R_Mesh_ColorPointer(NULL, 0, 0);
8461 R_Mesh_ResetTextureState();
8462 R_SetupGenericShader(false);
8463 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8465 GL_BlendFunc(GL_ONE, GL_ZERO);
8467 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8469 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8470 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8471 else if (!rsurface.texture->currentnumlayers)
8473 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8475 // in the deferred case, transparent surfaces were queued during prepass
8476 if (!r_shadow_usingdeferredprepass)
8477 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8481 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8482 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8487 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8491 // break the surface list down into batches by texture and use of lightmapping
8492 for (i = 0;i < numsurfaces;i = j)
8495 // texture is the base texture pointer, rsurface.texture is the
8496 // current frame/skin the texture is directing us to use (for example
8497 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8498 // use skin 1 instead)
8499 texture = surfacelist[i]->texture;
8500 rsurface.texture = R_GetCurrentTexture(texture);
8501 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8502 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8504 // if this texture is not the kind we want, skip ahead to the next one
8505 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8509 // simply scan ahead until we find a different texture or lightmap state
8510 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8512 // render the range of surfaces
8513 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
8517 float locboxvertex3f[6*4*3] =
8519 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8520 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8521 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8522 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8523 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8524 1,0,0, 0,0,0, 0,1,0, 1,1,0
8527 unsigned short locboxelements[6*2*3] =
8537 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8540 cl_locnode_t *loc = (cl_locnode_t *)ent;
8542 float vertex3f[6*4*3];
8544 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8545 GL_DepthMask(false);
8546 GL_DepthRange(0, 1);
8547 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8549 GL_CullFace(GL_NONE);
8550 R_Mesh_Matrix(&identitymatrix);
8552 R_Mesh_VertexPointer(vertex3f, 0, 0);
8553 R_Mesh_ColorPointer(NULL, 0, 0);
8554 R_Mesh_ResetTextureState();
8555 R_SetupGenericShader(false);
8558 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8559 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8560 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8561 surfacelist[0] < 0 ? 0.5f : 0.125f);
8563 if (VectorCompare(loc->mins, loc->maxs))
8565 VectorSet(size, 2, 2, 2);
8566 VectorMA(loc->mins, -0.5f, size, mins);
8570 VectorCopy(loc->mins, mins);
8571 VectorSubtract(loc->maxs, loc->mins, size);
8574 for (i = 0;i < 6*4*3;)
8575 for (j = 0;j < 3;j++, i++)
8576 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8578 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8581 void R_DrawLocs(void)
8584 cl_locnode_t *loc, *nearestloc;
8586 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8587 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8589 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8590 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8594 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8596 if (decalsystem->decals)
8597 Mem_Free(decalsystem->decals);
8598 memset(decalsystem, 0, sizeof(*decalsystem));
8601 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)
8608 // expand or initialize the system
8609 if (decalsystem->maxdecals <= decalsystem->numdecals)
8611 decalsystem_t old = *decalsystem;
8612 qboolean useshortelements;
8613 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8614 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8615 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)));
8616 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8617 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8618 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8619 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8620 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8621 if (decalsystem->numdecals)
8622 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8624 Mem_Free(old.decals);
8625 for (i = 0;i < decalsystem->maxdecals*3;i++)
8626 decalsystem->element3i[i] = i;
8627 if (useshortelements)
8628 for (i = 0;i < decalsystem->maxdecals*3;i++)
8629 decalsystem->element3s[i] = i;
8632 // grab a decal and search for another free slot for the next one
8633 maxdecals = decalsystem->maxdecals;
8634 decals = decalsystem->decals;
8635 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8636 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8638 decalsystem->freedecal = i;
8639 if (decalsystem->numdecals <= i)
8640 decalsystem->numdecals = i + 1;
8642 // initialize the decal
8644 decal->triangleindex = triangleindex;
8645 decal->surfaceindex = surfaceindex;
8646 decal->decalsequence = decalsequence;
8647 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8648 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8649 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8650 decal->color4ub[0][3] = 255;
8651 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8652 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8653 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8654 decal->color4ub[1][3] = 255;
8655 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8656 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8657 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8658 decal->color4ub[2][3] = 255;
8659 decal->vertex3f[0][0] = v0[0];
8660 decal->vertex3f[0][1] = v0[1];
8661 decal->vertex3f[0][2] = v0[2];
8662 decal->vertex3f[1][0] = v1[0];
8663 decal->vertex3f[1][1] = v1[1];
8664 decal->vertex3f[1][2] = v1[2];
8665 decal->vertex3f[2][0] = v2[0];
8666 decal->vertex3f[2][1] = v2[1];
8667 decal->vertex3f[2][2] = v2[2];
8668 decal->texcoord2f[0][0] = t0[0];
8669 decal->texcoord2f[0][1] = t0[1];
8670 decal->texcoord2f[1][0] = t1[0];
8671 decal->texcoord2f[1][1] = t1[1];
8672 decal->texcoord2f[2][0] = t2[0];
8673 decal->texcoord2f[2][1] = t2[1];
8676 extern cvar_t cl_decals_bias;
8677 extern cvar_t cl_decals_models;
8678 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8679 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)
8681 matrix4x4_t projection;
8682 decalsystem_t *decalsystem;
8685 const float *vertex3f;
8686 const msurface_t *surface;
8687 const msurface_t *surfaces;
8688 const int *surfacelist;
8689 const texture_t *texture;
8693 int surfacelistindex;
8696 int decalsurfaceindex;
8701 float localorigin[3];
8702 float localnormal[3];
8713 float points[2][9][3];
8717 decalsystem = &ent->decalsystem;
8719 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8721 R_DecalSystem_Reset(&ent->decalsystem);
8725 if (!model->brush.data_nodes && !cl_decals_models.integer)
8727 if (decalsystem->model)
8728 R_DecalSystem_Reset(decalsystem);
8732 if (decalsystem->model != model)
8733 R_DecalSystem_Reset(decalsystem);
8734 decalsystem->model = model;
8736 RSurf_ActiveModelEntity(ent, false, false, false);
8738 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8739 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8740 VectorNormalize(localnormal);
8741 localsize = worldsize*rsurface.inversematrixscale;
8742 ilocalsize = 1.0f / localsize;
8743 localmins[0] = localorigin[0] - localsize;
8744 localmins[1] = localorigin[1] - localsize;
8745 localmins[2] = localorigin[2] - localsize;
8746 localmaxs[0] = localorigin[0] + localsize;
8747 localmaxs[1] = localorigin[1] + localsize;
8748 localmaxs[2] = localorigin[2] + localsize;
8750 //VectorCopy(localnormal, planes[4]);
8751 //VectorVectors(planes[4], planes[2], planes[0]);
8752 AnglesFromVectors(angles, localnormal, NULL, false);
8753 AngleVectors(angles, planes[0], planes[2], planes[4]);
8754 VectorNegate(planes[0], planes[1]);
8755 VectorNegate(planes[2], planes[3]);
8756 VectorNegate(planes[4], planes[5]);
8757 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8758 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8759 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8760 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8761 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8762 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8767 matrix4x4_t forwardprojection;
8768 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8769 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8774 float projectionvector[4][3];
8775 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8776 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8777 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8778 projectionvector[0][0] = planes[0][0] * ilocalsize;
8779 projectionvector[0][1] = planes[1][0] * ilocalsize;
8780 projectionvector[0][2] = planes[2][0] * ilocalsize;
8781 projectionvector[1][0] = planes[0][1] * ilocalsize;
8782 projectionvector[1][1] = planes[1][1] * ilocalsize;
8783 projectionvector[1][2] = planes[2][1] * ilocalsize;
8784 projectionvector[2][0] = planes[0][2] * ilocalsize;
8785 projectionvector[2][1] = planes[1][2] * ilocalsize;
8786 projectionvector[2][2] = planes[2][2] * ilocalsize;
8787 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8788 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8789 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8790 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8794 dynamic = model->surfmesh.isanimated;
8795 vertex3f = rsurface.modelvertex3f;
8796 numsurfacelist = model->nummodelsurfaces;
8797 surfacelist = model->sortedmodelsurfaces;
8798 surfaces = model->data_surfaces;
8799 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8801 surfaceindex = surfacelist[surfacelistindex];
8802 surface = surfaces + surfaceindex;
8803 // skip transparent surfaces
8804 texture = surface->texture;
8805 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8807 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8809 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8811 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8812 numvertices = surface->num_vertices;
8813 numtriangles = surface->num_triangles;
8814 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8816 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8818 index = 3*e[cornerindex];
8819 VectorCopy(vertex3f + index, v[cornerindex]);
8822 //TriangleNormal(v[0], v[1], v[2], normal);
8823 //if (DotProduct(normal, localnormal) < 0.0f)
8825 // clip by each of the box planes formed from the projection matrix
8826 // if anything survives, we emit the decal
8827 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]);
8830 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]);
8833 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]);
8836 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]);
8839 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]);
8842 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]);
8845 // some part of the triangle survived, so we have to accept it...
8848 // dynamic always uses the original triangle
8850 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8852 index = 3*e[cornerindex];
8853 VectorCopy(vertex3f + index, v[cornerindex]);
8856 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8858 // convert vertex positions to texcoords
8859 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8860 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8861 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8862 // calculate distance fade from the projection origin
8863 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8864 f = bound(0.0f, f, 1.0f);
8865 c[cornerindex][0] = r * f;
8866 c[cornerindex][1] = g * f;
8867 c[cornerindex][2] = b * f;
8868 c[cornerindex][3] = 1.0f;
8869 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8872 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);
8874 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8875 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, surfaceindex, decalsequence);
8880 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8881 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)
8883 int renderentityindex;
8886 entity_render_t *ent;
8888 if (!cl_decals_newsystem.integer)
8891 worldmins[0] = worldorigin[0] - worldsize;
8892 worldmins[1] = worldorigin[1] - worldsize;
8893 worldmins[2] = worldorigin[2] - worldsize;
8894 worldmaxs[0] = worldorigin[0] + worldsize;
8895 worldmaxs[1] = worldorigin[1] + worldsize;
8896 worldmaxs[2] = worldorigin[2] + worldsize;
8898 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8900 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8902 ent = r_refdef.scene.entities[renderentityindex];
8903 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8906 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8910 typedef struct r_decalsystem_splatqueue_s
8919 r_decalsystem_splatqueue_t;
8921 int r_decalsystem_numqueued = 0;
8922 #define MAX_DECALSYSTEM_QUEUE 1024
8923 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8925 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)
8927 r_decalsystem_splatqueue_t *queue;
8929 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8932 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8933 VectorCopy(worldorigin, queue->worldorigin);
8934 VectorCopy(worldnormal, queue->worldnormal);
8935 Vector4Set(queue->color, r, g, b, a);
8936 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8937 queue->worldsize = worldsize;
8938 queue->decalsequence = cl.decalsequence++;
8941 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8944 r_decalsystem_splatqueue_t *queue;
8946 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8947 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);
8948 r_decalsystem_numqueued = 0;
8951 extern cvar_t cl_decals_max;
8952 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8955 decalsystem_t *decalsystem = &ent->decalsystem;
8962 if (!decalsystem->numdecals)
8965 if (r_showsurfaces.integer)
8968 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8970 R_DecalSystem_Reset(decalsystem);
8974 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8975 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8977 if (decalsystem->lastupdatetime)
8978 frametime = (cl.time - decalsystem->lastupdatetime);
8981 decalsystem->lastupdatetime = cl.time;
8982 decal = decalsystem->decals;
8983 numdecals = decalsystem->numdecals;
8985 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8987 if (decal->color4ub[0][3])
8989 decal->lived += frametime;
8990 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
8992 memset(decal, 0, sizeof(*decal));
8993 if (decalsystem->freedecal > i)
8994 decalsystem->freedecal = i;
8998 decal = decalsystem->decals;
8999 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
9002 // collapse the array by shuffling the tail decals into the gaps
9005 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
9006 decalsystem->freedecal++;
9007 if (decalsystem->freedecal == numdecals)
9009 decal[decalsystem->freedecal] = decal[--numdecals];
9012 decalsystem->numdecals = numdecals;
9016 // if there are no decals left, reset decalsystem
9017 R_DecalSystem_Reset(decalsystem);
9021 extern skinframe_t *decalskinframe;
9022 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9025 decalsystem_t *decalsystem = &ent->decalsystem;
9035 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9038 numdecals = decalsystem->numdecals;
9042 if (r_showsurfaces.integer)
9045 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9047 R_DecalSystem_Reset(decalsystem);
9051 // if the model is static it doesn't matter what value we give for
9052 // wantnormals and wanttangents, so this logic uses only rules applicable
9053 // to a model, knowing that they are meaningless otherwise
9054 if (ent == r_refdef.scene.worldentity)
9055 RSurf_ActiveWorldEntity();
9057 RSurf_ActiveModelEntity(ent, false, false, false);
9059 decalsystem->lastupdatetime = cl.time;
9060 decal = decalsystem->decals;
9062 fadedelay = cl_decals_time.value;
9063 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9065 // update vertex positions for animated models
9066 v3f = decalsystem->vertex3f;
9067 c4f = decalsystem->color4f;
9068 t2f = decalsystem->texcoord2f;
9069 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9071 if (!decal->color4ub[0][3])
9074 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9077 // update color values for fading decals
9078 if (decal->lived >= cl_decals_time.value)
9080 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9081 alpha *= (1.0f/255.0f);
9084 alpha = 1.0f/255.0f;
9086 c4f[ 0] = decal->color4ub[0][0] * alpha;
9087 c4f[ 1] = decal->color4ub[0][1] * alpha;
9088 c4f[ 2] = decal->color4ub[0][2] * alpha;
9090 c4f[ 4] = decal->color4ub[1][0] * alpha;
9091 c4f[ 5] = decal->color4ub[1][1] * alpha;
9092 c4f[ 6] = decal->color4ub[1][2] * alpha;
9094 c4f[ 8] = decal->color4ub[2][0] * alpha;
9095 c4f[ 9] = decal->color4ub[2][1] * alpha;
9096 c4f[10] = decal->color4ub[2][2] * alpha;
9099 t2f[0] = decal->texcoord2f[0][0];
9100 t2f[1] = decal->texcoord2f[0][1];
9101 t2f[2] = decal->texcoord2f[1][0];
9102 t2f[3] = decal->texcoord2f[1][1];
9103 t2f[4] = decal->texcoord2f[2][0];
9104 t2f[5] = decal->texcoord2f[2][1];
9106 // update vertex positions for animated models
9107 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9109 e = rsurface.modelelement3i + 3*decal->triangleindex;
9110 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9111 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9112 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9116 VectorCopy(decal->vertex3f[0], v3f);
9117 VectorCopy(decal->vertex3f[1], v3f + 3);
9118 VectorCopy(decal->vertex3f[2], v3f + 6);
9129 r_refdef.stats.drawndecals += numtris;
9131 if (r_refdef.fogenabled)
9133 switch(vid.renderpath)
9135 case RENDERPATH_GL20:
9136 case RENDERPATH_GL13:
9137 case RENDERPATH_GL11:
9138 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
9140 alpha = RSurf_FogVertex(v3f);
9149 // now render the decals all at once
9150 // (this assumes they all use one particle font texture!)
9151 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);
9152 R_Mesh_ResetTextureState();
9153 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9154 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9155 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9156 R_SetupGenericShader(true);
9157 GL_DepthMask(false);
9158 GL_DepthRange(0, 1);
9159 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9161 GL_CullFace(GL_NONE);
9162 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9163 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
9164 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
9165 GL_LockArrays(0, numtris * 3);
9166 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9167 GL_LockArrays(0, 0);
9171 static void R_DrawModelDecals(void)
9175 // fade faster when there are too many decals
9176 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9177 for (i = 0;i < r_refdef.scene.numentities;i++)
9178 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9180 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9181 for (i = 0;i < r_refdef.scene.numentities;i++)
9182 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9183 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9185 R_DecalSystem_ApplySplatEntitiesQueue();
9187 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9188 for (i = 0;i < r_refdef.scene.numentities;i++)
9189 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9191 r_refdef.stats.totaldecals += numdecals;
9193 if (r_showsurfaces.integer)
9196 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9198 for (i = 0;i < r_refdef.scene.numentities;i++)
9200 if (!r_refdef.viewcache.entityvisible[i])
9202 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9203 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9207 void R_DrawDebugModel(void)
9209 entity_render_t *ent = rsurface.entity;
9210 int i, j, k, l, flagsmask;
9211 const int *elements;
9213 const msurface_t *surface;
9214 dp_model_t *model = ent->model;
9217 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9219 R_Mesh_ColorPointer(NULL, 0, 0);
9220 R_Mesh_ResetTextureState();
9221 R_SetupGenericShader(false);
9222 GL_DepthRange(0, 1);
9223 GL_DepthTest(!r_showdisabledepthtest.integer);
9224 GL_DepthMask(false);
9225 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9227 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
9229 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9230 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
9232 if (brush->colbrushf && brush->colbrushf->numtriangles)
9234 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
9235 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);
9236 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
9239 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
9241 if (surface->num_collisiontriangles)
9243 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
9244 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);
9245 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
9250 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9252 if (r_showtris.integer || r_shownormals.integer)
9254 if (r_showdisabledepthtest.integer)
9256 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9257 GL_DepthMask(false);
9261 GL_BlendFunc(GL_ONE, GL_ZERO);
9264 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9266 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9268 rsurface.texture = R_GetCurrentTexture(surface->texture);
9269 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9271 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
9272 if (r_showtris.value > 0)
9274 if (!rsurface.texture->currentlayers->depthmask)
9275 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9276 else if (ent == r_refdef.scene.worldentity)
9277 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9279 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9280 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
9281 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
9282 R_Mesh_ColorPointer(NULL, 0, 0);
9283 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
9284 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9285 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
9286 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);
9287 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9290 if (r_shownormals.value < 0)
9293 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9295 VectorCopy(rsurface.vertex3f + l * 3, v);
9296 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9297 qglVertex3f(v[0], v[1], v[2]);
9298 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
9299 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9300 qglVertex3f(v[0], v[1], v[2]);
9305 if (r_shownormals.value > 0)
9308 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9310 VectorCopy(rsurface.vertex3f + l * 3, v);
9311 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9312 qglVertex3f(v[0], v[1], v[2]);
9313 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
9314 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9315 qglVertex3f(v[0], v[1], v[2]);
9320 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9322 VectorCopy(rsurface.vertex3f + l * 3, v);
9323 GL_Color(0, r_refdef.view.colorscale, 0, 1);
9324 qglVertex3f(v[0], v[1], v[2]);
9325 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
9326 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9327 qglVertex3f(v[0], v[1], v[2]);
9332 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9334 VectorCopy(rsurface.vertex3f + l * 3, v);
9335 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9336 qglVertex3f(v[0], v[1], v[2]);
9337 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
9338 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9339 qglVertex3f(v[0], v[1], v[2]);
9346 rsurface.texture = NULL;
9350 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
9351 int r_maxsurfacelist = 0;
9352 const msurface_t **r_surfacelist = NULL;
9353 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9355 int i, j, endj, f, flagsmask;
9357 dp_model_t *model = r_refdef.scene.worldmodel;
9358 msurface_t *surfaces;
9359 unsigned char *update;
9360 int numsurfacelist = 0;
9364 if (r_maxsurfacelist < model->num_surfaces)
9366 r_maxsurfacelist = model->num_surfaces;
9368 Mem_Free((msurface_t**)r_surfacelist);
9369 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9372 RSurf_ActiveWorldEntity();
9374 surfaces = model->data_surfaces;
9375 update = model->brushq1.lightmapupdateflags;
9377 // update light styles on this submodel
9378 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9380 model_brush_lightstyleinfo_t *style;
9381 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9383 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9385 int *list = style->surfacelist;
9386 style->value = r_refdef.scene.lightstylevalue[style->style];
9387 for (j = 0;j < style->numsurfaces;j++)
9388 update[list[j]] = true;
9393 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9398 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9404 rsurface.uselightmaptexture = false;
9405 rsurface.texture = NULL;
9406 rsurface.rtlight = NULL;
9408 // add visible surfaces to draw list
9409 for (i = 0;i < model->nummodelsurfaces;i++)
9411 j = model->sortedmodelsurfaces[i];
9412 if (r_refdef.viewcache.world_surfacevisible[j])
9413 r_surfacelist[numsurfacelist++] = surfaces + j;
9415 // update lightmaps if needed
9417 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9418 if (r_refdef.viewcache.world_surfacevisible[j])
9420 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9421 // don't do anything if there were no surfaces
9422 if (!numsurfacelist)
9424 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9427 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9428 GL_AlphaTest(false);
9430 // add to stats if desired
9431 if (r_speeds.integer && !skysurfaces && !depthonly)
9433 r_refdef.stats.world_surfaces += numsurfacelist;
9434 for (j = 0;j < numsurfacelist;j++)
9435 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9438 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9441 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9443 int i, j, endj, f, flagsmask;
9445 dp_model_t *model = ent->model;
9446 msurface_t *surfaces;
9447 unsigned char *update;
9448 int numsurfacelist = 0;
9452 if (r_maxsurfacelist < model->num_surfaces)
9454 r_maxsurfacelist = model->num_surfaces;
9456 Mem_Free((msurface_t **)r_surfacelist);
9457 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9460 // if the model is static it doesn't matter what value we give for
9461 // wantnormals and wanttangents, so this logic uses only rules applicable
9462 // to a model, knowing that they are meaningless otherwise
9463 if (ent == r_refdef.scene.worldentity)
9464 RSurf_ActiveWorldEntity();
9465 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9466 RSurf_ActiveModelEntity(ent, false, false, false);
9468 RSurf_ActiveModelEntity(ent, true, true, true);
9470 RSurf_ActiveModelEntity(ent, false, false, false);
9473 switch (vid.renderpath)
9475 case RENDERPATH_GL20:
9476 RSurf_ActiveModelEntity(ent, true, true, false);
9478 case RENDERPATH_GL13:
9479 case RENDERPATH_GL11:
9480 RSurf_ActiveModelEntity(ent, true, false, false);
9485 surfaces = model->data_surfaces;
9486 update = model->brushq1.lightmapupdateflags;
9488 // update light styles
9489 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9491 model_brush_lightstyleinfo_t *style;
9492 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9494 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9496 int *list = style->surfacelist;
9497 style->value = r_refdef.scene.lightstylevalue[style->style];
9498 for (j = 0;j < style->numsurfaces;j++)
9499 update[list[j]] = true;
9504 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9509 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9515 rsurface.uselightmaptexture = false;
9516 rsurface.texture = NULL;
9517 rsurface.rtlight = NULL;
9519 // add visible surfaces to draw list
9520 for (i = 0;i < model->nummodelsurfaces;i++)
9521 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9522 // don't do anything if there were no surfaces
9523 if (!numsurfacelist)
9525 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9528 // update lightmaps if needed
9530 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9532 R_BuildLightMap(ent, surfaces + j);
9533 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9534 GL_AlphaTest(false);
9536 // add to stats if desired
9537 if (r_speeds.integer && !skysurfaces && !depthonly)
9539 r_refdef.stats.entities_surfaces += numsurfacelist;
9540 for (j = 0;j < numsurfacelist;j++)
9541 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9544 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9547 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
9549 static texture_t texture;
9550 static msurface_t surface;
9551 const msurface_t *surfacelist = &surface;
9553 // fake enough texture and surface state to render this geometry
9555 texture.update_lastrenderframe = -1; // regenerate this texture
9556 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9557 texture.currentskinframe = skinframe;
9558 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9559 texture.specularscalemod = 1;
9560 texture.specularpowermod = 1;
9562 surface.texture = &texture;
9563 surface.num_triangles = numtriangles;
9564 surface.num_firsttriangle = firsttriangle;
9565 surface.num_vertices = numvertices;
9566 surface.num_firstvertex = firstvertex;
9569 rsurface.texture = R_GetCurrentTexture(surface.texture);
9570 rsurface.uselightmaptexture = false;
9571 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
9574 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)
9576 static msurface_t surface;
9577 const msurface_t *surfacelist = &surface;
9579 // fake enough texture and surface state to render this geometry
9581 surface.texture = texture;
9582 surface.num_triangles = numtriangles;
9583 surface.num_firsttriangle = firsttriangle;
9584 surface.num_vertices = numvertices;
9585 surface.num_firstvertex = firstvertex;
9588 rsurface.texture = R_GetCurrentTexture(surface.texture);
9589 rsurface.uselightmaptexture = false;
9590 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);