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", "0", "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_PERSISTENT, NULL);
292 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
297 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
302 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, 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_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_CLAMP | TEXF_PERSISTENT, NULL);
340 static void R_BuildNormalizationCube(void)
344 vec_t s, t, intensity;
347 data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
348 for (side = 0;side < 6;side++)
350 for (y = 0;y < NORMSIZE;y++)
352 for (x = 0;x < NORMSIZE;x++)
354 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
355 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
390 intensity = 127.0f / sqrt(DotProduct(v, v));
391 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
392 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
393 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
394 data[((side*64+y)*64+x)*4+3] = 255;
398 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
402 static void R_BuildFogTexture(void)
406 unsigned char data1[FOGWIDTH][4];
407 //unsigned char data2[FOGWIDTH][4];
410 r_refdef.fogmasktable_start = r_refdef.fog_start;
411 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
412 r_refdef.fogmasktable_range = r_refdef.fogrange;
413 r_refdef.fogmasktable_density = r_refdef.fog_density;
415 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
416 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
418 d = (x * r - r_refdef.fogmasktable_start);
419 if(developer.integer >= 100)
420 Con_Printf("%f ", d);
422 if (r_fog_exp2.integer)
423 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
425 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
426 if(developer.integer >= 100)
427 Con_Printf(" : %f ", alpha);
428 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
429 if(developer.integer >= 100)
430 Con_Printf(" = %f\n", alpha);
431 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
434 for (x = 0;x < FOGWIDTH;x++)
436 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
441 //data2[x][0] = 255 - b;
442 //data2[x][1] = 255 - b;
443 //data2[x][2] = 255 - b;
446 if (r_texture_fogattenuation)
448 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
449 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
453 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
454 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
458 static const char *builtinshaderstring =
459 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
460 "// written by Forest 'LordHavoc' Hale\n"
462 "// enable various extensions depending on permutation:\n"
464 "#ifdef MODE_DEPTH_OR_SHADOW\n"
465 "#ifdef VERTEX_SHADER\n"
468 " gl_Position = ftransform();\n"
471 "#else // !MODE_DEPTH_ORSHADOW\n"
472 "#ifdef MODE_SHOWDEPTH\n"
473 "#ifdef VERTEX_SHADER\n"
476 " gl_Position = ftransform();\n"
477 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
481 "#ifdef FRAGMENT_SHADER\n"
484 " gl_FragColor = gl_Color;\n"
487 "#else // !MODE_SHOWDEPTH\n"
488 "#ifdef MODE_POSTPROCESS\n"
489 "varying vec2 TexCoord1;\n"
490 "varying vec2 TexCoord2;\n"
492 "#ifdef VERTEX_SHADER\n"
495 " gl_Position = ftransform();\n"
496 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
498 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
503 "#ifdef FRAGMENT_SHADER\n"
504 "uniform sampler2D Texture_First;\n"
506 "uniform sampler2D Texture_Second;\n"
508 "#ifdef USEGAMMARAMPS\n"
509 "uniform sampler2D Texture_GammaRamps;\n"
511 "#ifdef USESATURATION\n"
512 "uniform float Saturation;\n"
514 "#ifdef USEVIEWTINT\n"
515 "uniform vec4 ViewTintColor;\n"
517 "//uncomment these if you want to use them:\n"
518 "uniform vec4 UserVec1;\n"
519 "// uniform vec4 UserVec2;\n"
520 "// uniform vec4 UserVec3;\n"
521 "// uniform vec4 UserVec4;\n"
522 "// uniform float ClientTime;\n"
523 "uniform vec2 PixelSize;\n"
526 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
528 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
530 "#ifdef USEVIEWTINT\n"
531 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
534 "#ifdef USEPOSTPROCESSING\n"
535 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
536 "// 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"
537 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
538 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
539 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
540 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
541 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
542 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
545 "#ifdef USESATURATION\n"
546 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
547 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
548 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
549 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
552 "#ifdef USEGAMMARAMPS\n"
553 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
554 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
555 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
559 "#else // !MODE_POSTPROCESS\n"
560 "#ifdef MODE_GENERIC\n"
561 "#ifdef USEDIFFUSE\n"
562 "varying vec2 TexCoord1;\n"
564 "#ifdef USESPECULAR\n"
565 "varying vec2 TexCoord2;\n"
567 "#ifdef VERTEX_SHADER\n"
570 " gl_FrontColor = gl_Color;\n"
571 "#ifdef USEDIFFUSE\n"
572 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
574 "#ifdef USESPECULAR\n"
575 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
577 " gl_Position = ftransform();\n"
581 "#ifdef FRAGMENT_SHADER\n"
582 "#ifdef USEDIFFUSE\n"
583 "uniform sampler2D Texture_First;\n"
585 "#ifdef USESPECULAR\n"
586 "uniform sampler2D Texture_Second;\n"
591 " gl_FragColor = gl_Color;\n"
592 "#ifdef USEDIFFUSE\n"
593 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
596 "#ifdef USESPECULAR\n"
597 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
599 "#ifdef USECOLORMAPPING\n"
600 " gl_FragColor *= tex2;\n"
603 " gl_FragColor += tex2;\n"
605 "#ifdef USEVERTEXTEXTUREBLEND\n"
606 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
610 "#else // !MODE_GENERIC\n"
611 "#ifdef MODE_BLOOMBLUR\n"
612 "varying TexCoord;\n"
613 "#ifdef VERTEX_SHADER\n"
616 " gl_FrontColor = gl_Color;\n"
617 " TexCoord = gl_MultiTexCoord0.xy;\n"
618 " gl_Position = ftransform();\n"
622 "#ifdef FRAGMENT_SHADER\n"
623 "uniform sampler2D Texture_First;\n"
624 "uniform vec4 BloomBlur_Parameters;\n"
629 " vec2 tc = TexCoord;\n"
630 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
631 " tc += BloomBlur_Parameters.xy;\n"
632 " for (i = 1;i < SAMPLES;i++)\n"
634 " color += texture2D(Texture_First, tc).rgb;\n"
635 " tc += BloomBlur_Parameters.xy;\n"
637 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
640 "#else // !MODE_BLOOMBLUR\n"
641 "#ifdef MODE_REFRACTION\n"
642 "varying vec2 TexCoord;\n"
643 "varying vec4 ModelViewProjectionPosition;\n"
644 "uniform mat4 TexMatrix;\n"
645 "#ifdef VERTEX_SHADER\n"
649 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
650 " gl_Position = ftransform();\n"
651 " ModelViewProjectionPosition = gl_Position;\n"
655 "#ifdef FRAGMENT_SHADER\n"
656 "uniform sampler2D Texture_Normal;\n"
657 "uniform sampler2D Texture_Refraction;\n"
658 "uniform sampler2D Texture_Reflection;\n"
660 "uniform vec4 DistortScaleRefractReflect;\n"
661 "uniform vec4 ScreenScaleRefractReflect;\n"
662 "uniform vec4 ScreenCenterRefractReflect;\n"
663 "uniform vec4 RefractColor;\n"
664 "uniform vec4 ReflectColor;\n"
665 "uniform float ReflectFactor;\n"
666 "uniform float ReflectOffset;\n"
670 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
671 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
672 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
673 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
674 " // FIXME temporary hack to detect the case that the reflection\n"
675 " // gets blackened at edges due to leaving the area that contains actual\n"
677 " // Remove this 'ack once we have a better way to stop this thing from\n"
679 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
680 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
681 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
682 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
683 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
684 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
687 "#else // !MODE_REFRACTION\n"
688 "#ifdef MODE_WATER\n"
689 "varying vec2 TexCoord;\n"
690 "varying vec3 EyeVector;\n"
691 "varying vec4 ModelViewProjectionPosition;\n"
692 "#ifdef VERTEX_SHADER\n"
693 "uniform vec3 EyePosition;\n"
694 "uniform mat4 TexMatrix;\n"
698 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
699 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
700 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
701 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
702 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
703 " gl_Position = ftransform();\n"
704 " ModelViewProjectionPosition = gl_Position;\n"
708 "#ifdef FRAGMENT_SHADER\n"
709 "uniform sampler2D Texture_Normal;\n"
710 "uniform sampler2D Texture_Refraction;\n"
711 "uniform sampler2D Texture_Reflection;\n"
713 "uniform vec4 DistortScaleRefractReflect;\n"
714 "uniform vec4 ScreenScaleRefractReflect;\n"
715 "uniform vec4 ScreenCenterRefractReflect;\n"
716 "uniform vec4 RefractColor;\n"
717 "uniform vec4 ReflectColor;\n"
718 "uniform float ReflectFactor;\n"
719 "uniform float ReflectOffset;\n"
723 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
724 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
725 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
726 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
727 " // FIXME temporary hack to detect the case that the reflection\n"
728 " // gets blackened at edges due to leaving the area that contains actual\n"
730 " // Remove this 'ack once we have a better way to stop this thing from\n"
732 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
733 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
734 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
735 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
736 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
737 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
738 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
739 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
740 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
741 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
742 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
743 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
746 "#else // !MODE_WATER\n"
748 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
749 "# extension GL_ARB_texture_rectangle : enable\n"
752 "#ifdef USESHADOWMAP2D\n"
753 "# ifdef GL_EXT_gpu_shader4\n"
754 "# extension GL_EXT_gpu_shader4 : enable\n"
756 "# ifdef GL_ARB_texture_gather\n"
757 "# extension GL_ARB_texture_gather : enable\n"
759 "# ifdef GL_AMD_texture_texture4\n"
760 "# extension GL_AMD_texture_texture4 : enable\n"
765 "#ifdef USESHADOWMAPCUBE\n"
766 "# extension GL_EXT_gpu_shader4 : enable\n"
769 "#ifdef USESHADOWSAMPLER\n"
770 "# extension GL_ARB_shadow : enable\n"
773 "// common definitions between vertex shader and fragment shader:\n"
775 "//#ifdef __GLSL_CG_DATA_TYPES\n"
776 "//# define myhalf half\n"
777 "//# define myhalf2 half2\n"
778 "//# define myhalf3half3\n"
779 "//# define myhalf4 half4\n"
781 "# define myhalf float\n"
782 "# define myhalf2 vec2\n"
783 "# define myhalf3 vec3\n"
784 "# define myhalf4 vec4\n"
787 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
791 "varying vec2 TexCoord;\n"
792 "#ifdef USEVERTEXTEXTUREBLEND\n"
793 "varying vec2 TexCoord2;\n"
795 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
796 "#define USELIGHTMAP\n"
797 "varying vec2 TexCoordLightmap;\n"
800 "#ifdef MODE_LIGHTSOURCE\n"
801 "varying vec3 CubeVector;\n"
804 "#ifdef MODE_LIGHTSOURCE\n"
805 "varying vec3 LightVector;\n"
807 "#if defined(MODE_LIGHTDIRECTION)\n"
808 "varying vec3 LightVector;\n"
811 "#if defined(USEOFFSETMAPPING) || defined(USESPECULAR)\n"
812 "//#if defined(USEOFFSETMAPPING) || defined(USESPECULAR) || defined(MODE_LIGHTDIRECTION) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
813 "#define USEEYEVECTOR\n"
814 "varying vec3 EyeVector;\n"
817 "varying vec3 EyeVectorModelSpace;\n"
818 "varying float FogPlaneVertexDist;\n"
821 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
822 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
823 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
824 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
827 "#ifdef USEREFLECTION\n"
828 "varying vec4 ModelViewProjectionPosition;\n"
830 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
831 "uniform vec3 LightPosition;\n"
832 "varying vec4 ModelViewPosition;\n"
835 "#ifdef MODE_LIGHTSOURCE\n"
836 "uniform vec3 LightPosition;\n"
838 "uniform vec3 EyePosition;\n"
839 "#ifdef MODE_LIGHTDIRECTION\n"
840 "uniform vec3 LightDir;\n"
842 "uniform vec4 FogPlane;\n"
848 "// vertex shader specific:\n"
849 "#ifdef VERTEX_SHADER\n"
851 "// 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"
853 "#ifdef MODE_DEFERREDGEOMETRY\n"
854 "uniform mat4 TexMatrix;\n"
855 "#ifdef USEVERTEXTEXTUREBLEND\n"
856 "uniform mat4 BackgroundTexMatrix;\n"
860 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
861 "#ifdef USEVERTEXTEXTUREBLEND\n"
862 " gl_FrontColor = gl_Color;\n"
863 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
866 " // transform unnormalized eye direction into tangent space\n"
867 "#ifdef USEOFFSETMAPPING\n"
868 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
869 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
870 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
871 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
874 " VectorS = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz).xyz;\n"
875 " VectorT = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz).xyz;\n"
876 " VectorR = normalize(gl_NormalMatrix * gl_MultiTexCoord3.xyz).xyz;\n"
877 " gl_Position = ftransform();\n"
879 "#else // !MODE_DEFERREDGEOMETRY\n"
880 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
883 " ModelViewPosition = gl_ModelViewMatrix * gl_Vertex;\n"
884 " gl_Position = ftransform();\n"
886 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
887 "uniform mat4 TexMatrix;\n"
888 "#ifdef USEVERTEXTEXTUREBLEND\n"
889 "uniform mat4 BackgroundTexMatrix;\n"
891 "#ifdef MODE_LIGHTSOURCE\n"
892 "uniform mat4 ModelToLight;\n"
896 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
897 " gl_FrontColor = gl_Color;\n"
899 " // copy the surface texcoord\n"
900 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
901 "#ifdef USEVERTEXTEXTUREBLEND\n"
902 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
904 "#ifdef USELIGHTMAP\n"
905 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
908 "#ifdef MODE_LIGHTSOURCE\n"
909 " // transform vertex position into light attenuation/cubemap space\n"
910 " // (-1 to +1 across the light box)\n"
911 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
913 "# ifdef USEDIFFUSE\n"
914 " // transform unnormalized light direction into tangent space\n"
915 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
916 " // normalize it per pixel)\n"
917 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
918 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
919 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
920 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
924 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
925 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
926 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
927 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
930 " // transform unnormalized eye direction into tangent space\n"
931 "#ifdef USEEYEVECTOR\n"
933 " vec3 EyeVectorModelSpace;\n"
935 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
936 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
937 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
938 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
942 "#ifndef USEEYEVECTOR\n"
943 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
945 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
948 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
949 " VectorS = gl_MultiTexCoord1.xyz;\n"
950 " VectorT = gl_MultiTexCoord2.xyz;\n"
951 " VectorR = gl_MultiTexCoord3.xyz;\n"
954 "//#if defined(USEREFLECTION)\n"
955 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
956 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
957 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
960 "// transform vertex to camera space, using ftransform to match non-VS\n"
962 " gl_Position = ftransform();\n"
964 "#ifdef USEREFLECTION\n"
965 " ModelViewProjectionPosition = gl_Position;\n"
968 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
969 "#endif // !MODE_DEFERREDGEOMETRY\n"
971 "#endif // VERTEX_SHADER\n"
976 "// fragment shader specific:\n"
977 "#ifdef FRAGMENT_SHADER\n"
979 "uniform sampler2D Texture_Normal;\n"
980 "uniform sampler2D Texture_Color;\n"
981 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
982 "uniform sampler2D Texture_Gloss;\n"
985 "uniform sampler2D Texture_Glow;\n"
987 "#ifdef USEVERTEXTEXTUREBLEND\n"
988 "uniform sampler2D Texture_SecondaryNormal;\n"
989 "uniform sampler2D Texture_SecondaryColor;\n"
990 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
991 "uniform sampler2D Texture_SecondaryGloss;\n"
994 "uniform sampler2D Texture_SecondaryGlow;\n"
997 "#ifdef USECOLORMAPPING\n"
998 "uniform sampler2D Texture_Pants;\n"
999 "uniform sampler2D Texture_Shirt;\n"
1002 "uniform sampler2D Texture_FogMask;\n"
1004 "#ifdef USELIGHTMAP\n"
1005 "uniform sampler2D Texture_Lightmap;\n"
1007 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1008 "uniform sampler2D Texture_Deluxemap;\n"
1010 "#ifdef USEREFLECTION\n"
1011 "uniform sampler2D Texture_Reflection;\n"
1014 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1015 "uniform sampler2DRect Texture_ScreenDepth;\n"
1016 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
1018 "#ifdef USEDEFERREDLIGHTMAP\n"
1019 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
1020 "uniform sampler2DRect Texture_ScreenSpecular;\n"
1023 "uniform myhalf3 Color_Pants;\n"
1024 "uniform myhalf3 Color_Shirt;\n"
1025 "uniform myhalf3 FogColor;\n"
1028 "uniform float FogRangeRecip;\n"
1029 "uniform float FogPlaneViewDist;\n"
1030 "uniform float FogHeightFade;\n"
1031 "myhalf FogVertex(void)\n"
1034 "#ifdef USEFOGOUTSIDE\n"
1035 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1037 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1039 " return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1043 "#ifdef USEOFFSETMAPPING\n"
1044 "uniform float OffsetMapping_Scale;\n"
1045 "vec2 OffsetMapping(vec2 TexCoord)\n"
1047 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1048 " // 14 sample relief mapping: linear search and then binary search\n"
1049 " // this basically steps forward a small amount repeatedly until it finds\n"
1050 " // itself inside solid, then jitters forward and back using decreasing\n"
1051 " // amounts to find the impact\n"
1052 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1053 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1054 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1055 " vec3 RT = vec3(TexCoord, 1);\n"
1056 " OffsetVector *= 0.1;\n"
1057 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1058 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1059 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1060 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1061 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1062 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1063 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1064 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1065 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1066 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1067 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1068 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1069 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1070 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1073 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1074 " // this basically moves forward the full distance, and then backs up based\n"
1075 " // on height of samples\n"
1076 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1077 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1078 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1079 " TexCoord += OffsetVector;\n"
1080 " OffsetVector *= 0.333;\n"
1081 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1082 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1083 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1084 " return TexCoord;\n"
1087 "#endif // USEOFFSETMAPPING\n"
1089 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1090 "uniform sampler2D Texture_Attenuation;\n"
1091 "uniform samplerCube Texture_Cube;\n"
1093 "#ifdef USESHADOWMAPRECT\n"
1094 "# ifdef USESHADOWSAMPLER\n"
1095 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1097 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1101 "#ifdef USESHADOWMAP2D\n"
1102 "# ifdef USESHADOWSAMPLER\n"
1103 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1105 "uniform sampler2D Texture_ShadowMap2D;\n"
1109 "#ifdef USESHADOWMAPVSDCT\n"
1110 "uniform samplerCube Texture_CubeProjection;\n"
1113 "#ifdef USESHADOWMAPCUBE\n"
1114 "# ifdef USESHADOWSAMPLER\n"
1115 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1117 "uniform samplerCube Texture_ShadowMapCube;\n"
1121 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1122 "uniform vec2 ShadowMap_TextureScale;\n"
1123 "uniform vec4 ShadowMap_Parameters;\n"
1126 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1127 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1129 " vec3 adir = abs(dir);\n"
1130 "# ifndef USESHADOWMAPVSDCT\n"
1134 " if (adir.x > adir.y)\n"
1136 " if (adir.x > adir.z) // X\n"
1140 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1146 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1151 " if (adir.y > adir.z) // Y\n"
1155 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1161 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1165 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1166 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1167 " stc.z += ShadowMap_Parameters.z;\n"
1170 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1171 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1172 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1173 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1174 " stc.z += ShadowMap_Parameters.z;\n"
1178 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1180 "#ifdef USESHADOWMAPCUBE\n"
1181 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1183 " vec3 adir = abs(dir);\n"
1184 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1188 "# ifdef USESHADOWMAPRECT\n"
1189 "float ShadowMapCompare(vec3 dir)\n"
1191 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1193 "# ifdef USESHADOWSAMPLER\n"
1195 "# ifdef USESHADOWMAPPCF\n"
1196 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1197 " 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"
1199 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1204 "# ifdef USESHADOWMAPPCF\n"
1205 "# if USESHADOWMAPPCF > 1\n"
1206 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1207 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1208 " 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"
1209 " 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"
1210 " 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"
1211 " 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"
1212 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1213 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1215 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1216 " vec2 offset = fract(shadowmaptc.xy);\n"
1217 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1218 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1219 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1220 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1221 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1224 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1232 "# ifdef USESHADOWMAP2D\n"
1233 "float ShadowMapCompare(vec3 dir)\n"
1235 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1238 "# ifdef USESHADOWSAMPLER\n"
1239 "# ifdef USESHADOWMAPPCF\n"
1240 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1241 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1242 " 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"
1244 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1247 "# ifdef USESHADOWMAPPCF\n"
1248 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1249 "# ifdef GL_ARB_texture_gather\n"
1250 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1252 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1254 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1255 " center *= ShadowMap_TextureScale;\n"
1256 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1257 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1258 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1259 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1260 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1261 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1262 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1264 "# ifdef GL_EXT_gpu_shader4\n"
1265 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1267 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1269 "# if USESHADOWMAPPCF > 1\n"
1270 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1271 " center *= ShadowMap_TextureScale;\n"
1272 " 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"
1273 " 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"
1274 " 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"
1275 " 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"
1276 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1277 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1279 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1280 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1281 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1282 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1283 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1284 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1288 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1295 "# ifdef USESHADOWMAPCUBE\n"
1296 "float ShadowMapCompare(vec3 dir)\n"
1298 " // apply depth texture cubemap as light filter\n"
1299 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1301 "# ifdef USESHADOWSAMPLER\n"
1302 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1304 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1309 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1311 "#ifdef MODE_DEFERREDGEOMETRY\n"
1314 "#ifdef USEOFFSETMAPPING\n"
1315 " // apply offsetmapping\n"
1316 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1317 "#define TexCoord TexCoordOffset\n"
1320 "#ifdef USEALPHAKILL\n"
1321 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1325 "#ifdef USEVERTEXTEXTUREBLEND\n"
1326 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1327 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1328 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1329 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1332 "#ifdef USEVERTEXTEXTUREBLEND\n"
1333 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1335 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1338 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1340 "#else // !MODE_DEFERREDGEOMETRY\n"
1341 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1342 "uniform mat4 ViewToLight;\n"
1343 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1344 "uniform vec2 ScreenToDepth;\n"
1345 "uniform myhalf3 DeferredColor_Ambient;\n"
1346 "uniform myhalf3 DeferredColor_Diffuse;\n"
1347 "#ifdef USESPECULAR\n"
1348 "uniform myhalf3 DeferredColor_Specular;\n"
1349 "uniform myhalf SpecularPower;\n"
1353 " // calculate viewspace pixel position\n"
1355 " position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1356 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1357 " // decode viewspace pixel normal\n"
1358 " myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1359 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1360 " // surfacenormal = pixel normal in viewspace\n"
1361 " // LightVector = pixel to light in viewspace\n"
1362 " // CubeVector = position in lightspace\n"
1363 " // eyevector = pixel to view in viewspace\n"
1364 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1365 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1366 "#ifdef USEDIFFUSE\n"
1367 " // calculate diffuse shading\n"
1368 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1369 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1371 "#ifdef USESPECULAR\n"
1372 " // calculate directional shading\n"
1373 " vec3 eyevector = position * -1.0;\n"
1374 "# ifdef USEEXACTSPECULARMATH\n"
1375 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1377 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1378 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1382 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1383 " fade *= ShadowMapCompare(CubeVector);\n"
1386 "#ifdef USEDIFFUSE\n"
1387 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1389 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1391 "#ifdef USESPECULAR\n"
1392 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1394 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1397 "# ifdef USECUBEFILTER\n"
1398 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1399 " gl_FragData[0] *= cubecolor;\n"
1400 " gl_FragData[1] *= cubecolor;\n"
1403 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1404 "#ifdef USEDEFERREDLIGHTMAP\n"
1405 "uniform myhalf3 DeferredMod_Diffuse;\n"
1406 "uniform myhalf3 DeferredMod_Specular;\n"
1408 "uniform myhalf3 Color_Ambient;\n"
1409 "uniform myhalf3 Color_Diffuse;\n"
1410 "uniform myhalf3 Color_Specular;\n"
1411 "uniform myhalf SpecularPower;\n"
1413 "uniform myhalf3 Color_Glow;\n"
1415 "uniform myhalf Alpha;\n"
1416 "#ifdef USEREFLECTION\n"
1417 "uniform vec4 DistortScaleRefractReflect;\n"
1418 "uniform vec4 ScreenScaleRefractReflect;\n"
1419 "uniform vec4 ScreenCenterRefractReflect;\n"
1420 "uniform myhalf4 ReflectColor;\n"
1422 "#ifdef MODE_LIGHTDIRECTION\n"
1423 "uniform myhalf3 LightColor;\n"
1425 "#ifdef MODE_LIGHTSOURCE\n"
1426 "uniform myhalf3 LightColor;\n"
1430 "#ifdef USEOFFSETMAPPING\n"
1431 " // apply offsetmapping\n"
1432 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1433 "#define TexCoord TexCoordOffset\n"
1436 " // combine the diffuse textures (base, pants, shirt)\n"
1437 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1438 "#ifdef USEALPHAKILL\n"
1439 " if (color.a < 0.5)\n"
1442 " color.a *= Alpha;\n"
1443 "#ifdef USECOLORMAPPING\n"
1444 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1446 "#ifdef USEVERTEXTEXTUREBLEND\n"
1447 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1448 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1449 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1450 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1452 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1455 " // get the surface normal\n"
1456 "#ifdef USEVERTEXTEXTUREBLEND\n"
1457 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1459 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1462 " // get the material colors\n"
1463 " myhalf3 diffusetex = color.rgb;\n"
1464 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1465 "# ifdef USEVERTEXTEXTUREBLEND\n"
1466 " myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1468 " myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1475 "#ifdef MODE_LIGHTSOURCE\n"
1476 " // light source\n"
1477 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1478 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1479 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1480 "#ifdef USESPECULAR\n"
1481 "#ifdef USEEXACTSPECULARMATH\n"
1482 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1484 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1485 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1487 " color.rgb += glosstex * (specular * Color_Specular);\n"
1489 " color.rgb *= LightColor;\n"
1490 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1491 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1492 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1494 "# ifdef USECUBEFILTER\n"
1495 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1497 "#endif // MODE_LIGHTSOURCE\n"
1502 "#ifdef MODE_LIGHTDIRECTION\n"
1504 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1505 "#define lightcolor LightColor\n"
1506 "#endif // MODE_LIGHTDIRECTION\n"
1507 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1509 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1510 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1511 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1512 " // convert modelspace light vector to tangentspace\n"
1513 " myhalf3 lightnormal;\n"
1514 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1515 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1516 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1517 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1518 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1519 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1520 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1521 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1522 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1523 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1524 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1525 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1526 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1527 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1528 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1530 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1531 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1532 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1538 "#ifdef MODE_LIGHTMAP\n"
1539 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1540 "#endif // MODE_LIGHTMAP\n"
1541 "#ifdef MODE_VERTEXCOLOR\n"
1542 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1543 "#endif // MODE_VERTEXCOLOR\n"
1544 "#ifdef MODE_FLATCOLOR\n"
1545 " color.rgb = diffusetex * Color_Ambient;\n"
1546 "#endif // MODE_FLATCOLOR\n"
1552 "# ifdef USEDIFFUSE\n"
1553 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1554 "# ifdef USESPECULAR\n"
1555 "# ifdef USEEXACTSPECULARMATH\n"
1556 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1558 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1559 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1561 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1563 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1566 " color.rgb = diffusetex * Color_Ambient;\n"
1570 "#ifdef USEDEFERREDLIGHTMAP\n"
1571 " color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1572 " color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1576 "#ifdef USEVERTEXTEXTUREBLEND\n"
1577 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1579 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1584 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1587 " // 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"
1588 "#ifdef USEREFLECTION\n"
1589 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1590 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1591 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1592 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1593 " // FIXME temporary hack to detect the case that the reflection\n"
1594 " // gets blackened at edges due to leaving the area that contains actual\n"
1596 " // Remove this 'ack once we have a better way to stop this thing from\n"
1598 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1599 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1600 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1601 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1602 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1603 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1606 " gl_FragColor = vec4(color);\n"
1608 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1609 "#endif // !MODE_DEFERREDGEOMETRY\n"
1611 "#endif // FRAGMENT_SHADER\n"
1613 "#endif // !MODE_WATER\n"
1614 "#endif // !MODE_REFRACTION\n"
1615 "#endif // !MODE_BLOOMBLUR\n"
1616 "#endif // !MODE_GENERIC\n"
1617 "#endif // !MODE_POSTPROCESS\n"
1618 "#endif // !MODE_SHOWDEPTH\n"
1619 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1622 typedef struct shaderpermutationinfo_s
1624 const char *pretext;
1627 shaderpermutationinfo_t;
1629 typedef struct shadermodeinfo_s
1631 const char *vertexfilename;
1632 const char *geometryfilename;
1633 const char *fragmentfilename;
1634 const char *pretext;
1639 typedef enum shaderpermutation_e
1641 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1642 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1643 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1644 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1645 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1646 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1647 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1648 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1649 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1650 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1651 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1652 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1653 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1654 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1655 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1656 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1657 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1658 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1659 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1660 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1661 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1662 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1663 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1664 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1665 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1666 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
1667 SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
1668 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
1670 shaderpermutation_t;
1672 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1673 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1675 {"#define USEDIFFUSE\n", " diffuse"},
1676 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1677 {"#define USEVIEWTINT\n", " viewtint"},
1678 {"#define USECOLORMAPPING\n", " colormapping"},
1679 {"#define USESATURATION\n", " saturation"},
1680 {"#define USEFOGINSIDE\n", " foginside"},
1681 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1682 {"#define USEGAMMARAMPS\n", " gammaramps"},
1683 {"#define USECUBEFILTER\n", " cubefilter"},
1684 {"#define USEGLOW\n", " glow"},
1685 {"#define USEBLOOM\n", " bloom"},
1686 {"#define USESPECULAR\n", " specular"},
1687 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1688 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1689 {"#define USEREFLECTION\n", " reflection"},
1690 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1691 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1692 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1693 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1694 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1695 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1696 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1697 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1698 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1699 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1700 {"#define USEALPHAKILL\n", " alphakill"},
1703 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1704 typedef enum shadermode_e
1706 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1707 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1708 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1709 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1710 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1711 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1712 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1713 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1714 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1715 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1716 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1717 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1718 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1719 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1720 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1725 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1726 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1728 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1729 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1730 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1731 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1732 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1733 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1734 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1735 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1736 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1737 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1738 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1739 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1740 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1741 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1742 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1745 struct r_glsl_permutation_s;
1746 typedef struct r_glsl_permutation_s
1748 /// hash lookup data
1749 struct r_glsl_permutation_s *hashnext;
1751 unsigned int permutation;
1753 /// indicates if we have tried compiling this permutation already
1755 /// 0 if compilation failed
1757 /// locations of detected uniforms in program object, or -1 if not found
1758 int loc_Texture_First;
1759 int loc_Texture_Second;
1760 int loc_Texture_GammaRamps;
1761 int loc_Texture_Normal;
1762 int loc_Texture_Color;
1763 int loc_Texture_Gloss;
1764 int loc_Texture_Glow;
1765 int loc_Texture_SecondaryNormal;
1766 int loc_Texture_SecondaryColor;
1767 int loc_Texture_SecondaryGloss;
1768 int loc_Texture_SecondaryGlow;
1769 int loc_Texture_Pants;
1770 int loc_Texture_Shirt;
1771 int loc_Texture_FogMask;
1772 int loc_Texture_Lightmap;
1773 int loc_Texture_Deluxemap;
1774 int loc_Texture_Attenuation;
1775 int loc_Texture_Cube;
1776 int loc_Texture_Refraction;
1777 int loc_Texture_Reflection;
1778 int loc_Texture_ShadowMapRect;
1779 int loc_Texture_ShadowMapCube;
1780 int loc_Texture_ShadowMap2D;
1781 int loc_Texture_CubeProjection;
1782 int loc_Texture_ScreenDepth;
1783 int loc_Texture_ScreenNormalMap;
1784 int loc_Texture_ScreenDiffuse;
1785 int loc_Texture_ScreenSpecular;
1787 int loc_BloomBlur_Parameters;
1789 int loc_Color_Ambient;
1790 int loc_Color_Diffuse;
1791 int loc_Color_Specular;
1793 int loc_Color_Pants;
1794 int loc_Color_Shirt;
1795 int loc_DeferredColor_Ambient;
1796 int loc_DeferredColor_Diffuse;
1797 int loc_DeferredColor_Specular;
1798 int loc_DeferredMod_Diffuse;
1799 int loc_DeferredMod_Specular;
1800 int loc_DistortScaleRefractReflect;
1801 int loc_EyePosition;
1803 int loc_FogHeightFade;
1805 int loc_FogPlaneViewDist;
1806 int loc_FogRangeRecip;
1809 int loc_LightPosition;
1810 int loc_OffsetMapping_Scale;
1812 int loc_ReflectColor;
1813 int loc_ReflectFactor;
1814 int loc_ReflectOffset;
1815 int loc_RefractColor;
1817 int loc_ScreenCenterRefractReflect;
1818 int loc_ScreenScaleRefractReflect;
1819 int loc_ScreenToDepth;
1820 int loc_ShadowMap_Parameters;
1821 int loc_ShadowMap_TextureScale;
1822 int loc_SpecularPower;
1827 int loc_ViewTintColor;
1828 int loc_ViewToLight;
1829 int loc_ModelToLight;
1831 int loc_BackgroundTexMatrix;
1833 r_glsl_permutation_t;
1835 #define SHADERPERMUTATION_HASHSIZE 256
1837 /// information about each possible shader permutation
1838 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1839 /// currently selected permutation
1840 r_glsl_permutation_t *r_glsl_permutation;
1841 /// storage for permutations linked in the hash table
1842 memexpandablearray_t r_glsl_permutationarray;
1844 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1846 //unsigned int hashdepth = 0;
1847 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1848 r_glsl_permutation_t *p;
1849 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1851 if (p->mode == mode && p->permutation == permutation)
1853 //if (hashdepth > 10)
1854 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1859 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1861 p->permutation = permutation;
1862 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1863 r_glsl_permutationhash[mode][hashindex] = p;
1864 //if (hashdepth > 10)
1865 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1869 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1872 if (!filename || !filename[0])
1874 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1877 if (printfromdisknotice)
1878 Con_DPrintf("from disk %s... ", filename);
1879 return shaderstring;
1881 else if (!strcmp(filename, "glsl/default.glsl"))
1883 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1884 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1886 return shaderstring;
1889 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1892 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1893 int vertstrings_count = 0;
1894 int geomstrings_count = 0;
1895 int fragstrings_count = 0;
1896 char *vertexstring, *geometrystring, *fragmentstring;
1897 const char *vertstrings_list[32+3];
1898 const char *geomstrings_list[32+3];
1899 const char *fragstrings_list[32+3];
1900 char permutationname[256];
1907 permutationname[0] = 0;
1908 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1909 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1910 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1912 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1914 // the first pretext is which type of shader to compile as
1915 // (later these will all be bound together as a program object)
1916 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1917 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1918 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1920 // the second pretext is the mode (for example a light source)
1921 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1922 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1923 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1924 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1926 // now add all the permutation pretexts
1927 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1929 if (permutation & (1<<i))
1931 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1932 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1933 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1934 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1938 // keep line numbers correct
1939 vertstrings_list[vertstrings_count++] = "\n";
1940 geomstrings_list[geomstrings_count++] = "\n";
1941 fragstrings_list[fragstrings_count++] = "\n";
1945 // now append the shader text itself
1946 vertstrings_list[vertstrings_count++] = vertexstring;
1947 geomstrings_list[geomstrings_count++] = geometrystring;
1948 fragstrings_list[fragstrings_count++] = fragmentstring;
1950 // if any sources were NULL, clear the respective list
1952 vertstrings_count = 0;
1953 if (!geometrystring)
1954 geomstrings_count = 0;
1955 if (!fragmentstring)
1956 fragstrings_count = 0;
1958 // compile the shader program
1959 if (vertstrings_count + geomstrings_count + fragstrings_count)
1960 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1964 qglUseProgramObjectARB(p->program);CHECKGLERROR
1965 // look up all the uniform variable names we care about, so we don't
1966 // have to look them up every time we set them
1968 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1969 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1970 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1971 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1972 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1973 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1974 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1975 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1976 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1977 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1978 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1979 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1980 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1981 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1982 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1983 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1984 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1985 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1986 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1987 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1988 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1989 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1990 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1991 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1992 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
1993 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
1994 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
1995 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
1996 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
1997 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
1998 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1999 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
2000 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
2001 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
2002 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
2003 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
2004 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
2005 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
2006 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
2007 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
2008 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
2009 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
2010 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
2011 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
2012 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
2013 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
2014 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
2015 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
2016 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
2017 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
2018 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
2019 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
2020 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
2021 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
2022 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
2023 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
2024 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
2025 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
2026 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
2027 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
2028 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2029 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2030 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2031 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2032 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
2033 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
2034 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
2035 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
2036 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
2037 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
2038 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
2039 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
2040 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
2041 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
2042 // initialize the samplers to refer to the texture units we use
2043 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
2044 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
2045 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
2046 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
2047 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
2048 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
2049 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
2050 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2051 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2052 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2053 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
2054 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
2055 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
2056 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
2057 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
2058 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
2059 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
2060 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
2061 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
2062 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
2063 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
2064 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
2065 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
2066 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2067 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
2068 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2069 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
2070 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2072 if (developer.integer)
2073 Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2076 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
2080 Mem_Free(vertexstring);
2082 Mem_Free(geometrystring);
2084 Mem_Free(fragmentstring);
2087 void R_GLSL_Restart_f(void)
2089 unsigned int i, limit;
2090 r_glsl_permutation_t *p;
2091 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2092 for (i = 0;i < limit;i++)
2094 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2096 GL_Backend_FreeProgram(p->program);
2097 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2100 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2103 void R_GLSL_DumpShader_f(void)
2107 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2110 Con_Printf("failed to write to glsl/default.glsl\n");
2114 FS_Print(file, "/* The engine may define the following macros:\n");
2115 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2116 for (i = 0;i < SHADERMODE_COUNT;i++)
2117 FS_Print(file, shadermodeinfo[i].pretext);
2118 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2119 FS_Print(file, shaderpermutationinfo[i].pretext);
2120 FS_Print(file, "*/\n");
2121 FS_Print(file, builtinshaderstring);
2124 Con_Printf("glsl/default.glsl written\n");
2127 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
2129 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2130 if (r_glsl_permutation != perm)
2132 r_glsl_permutation = perm;
2133 if (!r_glsl_permutation->program)
2135 if (!r_glsl_permutation->compiled)
2136 R_GLSL_CompilePermutation(perm, mode, permutation);
2137 if (!r_glsl_permutation->program)
2139 // remove features until we find a valid permutation
2141 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2143 // reduce i more quickly whenever it would not remove any bits
2144 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2145 if (!(permutation & j))
2148 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2149 if (!r_glsl_permutation->compiled)
2150 R_GLSL_CompilePermutation(perm, mode, permutation);
2151 if (r_glsl_permutation->program)
2154 if (i >= SHADERPERMUTATION_COUNT)
2156 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2157 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2158 qglUseProgramObjectARB(0);CHECKGLERROR
2159 return; // no bit left to clear, entire mode is broken
2164 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2168 void R_SetupGenericShader(qboolean usetexture)
2170 switch(vid.renderpath)
2172 case RENDERPATH_GL20:
2173 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2175 case RENDERPATH_GL13:
2176 case RENDERPATH_GL11:
2181 void R_SetupGenericTwoTextureShader(int texturemode)
2183 switch (vid.renderpath)
2185 case RENDERPATH_GL20:
2186 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))));
2188 case RENDERPATH_GL13:
2189 case RENDERPATH_GL11:
2190 R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
2195 void R_SetupDepthOrShadowShader(void)
2197 switch (vid.renderpath)
2199 case RENDERPATH_GL20:
2200 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2202 case RENDERPATH_GL13:
2204 case RENDERPATH_GL11:
2209 void R_SetupShowDepthShader(void)
2211 switch (vid.renderpath)
2213 case RENDERPATH_GL20:
2214 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2216 case RENDERPATH_GL13:
2218 case RENDERPATH_GL11:
2223 extern qboolean r_shadow_usingdeferredprepass;
2224 extern cvar_t r_shadow_deferred_8bitrange;
2225 extern rtexture_t *r_shadow_attenuationgradienttexture;
2226 extern rtexture_t *r_shadow_attenuation2dtexture;
2227 extern rtexture_t *r_shadow_attenuation3dtexture;
2228 extern qboolean r_shadow_usingshadowmaprect;
2229 extern qboolean r_shadow_usingshadowmapcube;
2230 extern qboolean r_shadow_usingshadowmap2d;
2231 extern float r_shadow_shadowmap_texturescale[2];
2232 extern float r_shadow_shadowmap_parameters[4];
2233 extern qboolean r_shadow_shadowmapvsdct;
2234 extern qboolean r_shadow_shadowmapsampler;
2235 extern int r_shadow_shadowmappcf;
2236 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2238 // select a permutation of the lighting shader appropriate to this
2239 // combination of texture, entity, light source, and fogging, only use the
2240 // minimum features necessary to avoid wasting rendering time in the
2241 // fragment shader on features that are not being used
2242 unsigned int permutation = 0;
2243 unsigned int mode = 0;
2245 // TODO: implement geometry-shader based shadow volumes someday
2246 if (r_glsl_offsetmapping.integer)
2248 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2249 if (r_glsl_offsetmapping_reliefmapping.integer)
2250 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2252 if (rsurfacepass == RSURFPASS_BACKGROUND)
2254 // distorted background
2255 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2256 mode = SHADERMODE_WATER;
2258 mode = SHADERMODE_REFRACTION;
2260 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2262 // normalmap (deferred prepass), may use alpha test on diffuse
2263 mode = SHADERMODE_DEFERREDGEOMETRY;
2264 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2265 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2266 if (r_glsl_offsetmapping.integer)
2268 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2269 if (r_glsl_offsetmapping_reliefmapping.integer)
2270 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2273 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2276 mode = SHADERMODE_LIGHTSOURCE;
2277 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2278 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2279 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2280 permutation |= SHADERPERMUTATION_CUBEFILTER;
2281 if (diffusescale > 0)
2282 permutation |= SHADERPERMUTATION_DIFFUSE;
2283 if (specularscale > 0)
2284 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2285 if (r_refdef.fogenabled)
2286 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2287 if (rsurface.texture->colormapping)
2288 permutation |= SHADERPERMUTATION_COLORMAPPING;
2289 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2291 if (r_shadow_usingshadowmaprect)
2292 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2293 if (r_shadow_usingshadowmap2d)
2294 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2295 if (r_shadow_usingshadowmapcube)
2296 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2297 else if(r_shadow_shadowmapvsdct)
2298 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2300 if (r_shadow_shadowmapsampler)
2301 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2302 if (r_shadow_shadowmappcf > 1)
2303 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2304 else if (r_shadow_shadowmappcf)
2305 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2308 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2310 // unshaded geometry (fullbright or ambient model lighting)
2311 mode = SHADERMODE_FLATCOLOR;
2312 ambientscale = diffusescale = specularscale = 0;
2313 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2314 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2315 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2316 permutation |= SHADERPERMUTATION_GLOW;
2317 if (r_refdef.fogenabled)
2318 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2319 if (rsurface.texture->colormapping)
2320 permutation |= SHADERPERMUTATION_COLORMAPPING;
2321 if (r_glsl_offsetmapping.integer)
2323 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2324 if (r_glsl_offsetmapping_reliefmapping.integer)
2325 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2327 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2328 permutation |= SHADERPERMUTATION_REFLECTION;
2330 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2332 // directional model lighting
2333 mode = SHADERMODE_LIGHTDIRECTION;
2334 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2335 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2336 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2337 permutation |= SHADERPERMUTATION_GLOW;
2338 permutation |= SHADERPERMUTATION_DIFFUSE;
2339 if (specularscale > 0)
2340 permutation |= SHADERPERMUTATION_SPECULAR;
2341 if (r_refdef.fogenabled)
2342 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2343 if (rsurface.texture->colormapping)
2344 permutation |= SHADERPERMUTATION_COLORMAPPING;
2345 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2346 permutation |= SHADERPERMUTATION_REFLECTION;
2347 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2348 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2350 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2352 // ambient model lighting
2353 mode = SHADERMODE_LIGHTDIRECTION;
2354 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2355 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2356 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2357 permutation |= SHADERPERMUTATION_GLOW;
2358 if (r_refdef.fogenabled)
2359 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2360 if (rsurface.texture->colormapping)
2361 permutation |= SHADERPERMUTATION_COLORMAPPING;
2362 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2363 permutation |= SHADERPERMUTATION_REFLECTION;
2364 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2365 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2370 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2372 // deluxemapping (light direction texture)
2373 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2374 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2376 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2377 permutation |= SHADERPERMUTATION_DIFFUSE;
2378 if (specularscale > 0)
2379 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2381 else if (r_glsl_deluxemapping.integer >= 2)
2383 // fake deluxemapping (uniform light direction in tangentspace)
2384 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2385 permutation |= SHADERPERMUTATION_DIFFUSE;
2386 if (specularscale > 0)
2387 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2389 else if (rsurface.uselightmaptexture)
2391 // ordinary lightmapping (q1bsp, q3bsp)
2392 mode = SHADERMODE_LIGHTMAP;
2396 // ordinary vertex coloring (q3bsp)
2397 mode = SHADERMODE_VERTEXCOLOR;
2399 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2400 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2401 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2402 permutation |= SHADERPERMUTATION_GLOW;
2403 if (r_refdef.fogenabled)
2404 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2405 if (rsurface.texture->colormapping)
2406 permutation |= SHADERPERMUTATION_COLORMAPPING;
2407 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2408 permutation |= SHADERPERMUTATION_REFLECTION;
2409 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2410 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2412 if(permutation & SHADERPERMUTATION_SPECULAR)
2413 if(r_shadow_glossexact.integer)
2414 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2415 if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
2416 permutation |= SHADERPERMUTATION_ALPHAKILL;
2417 R_SetupShader_SetPermutation(mode, permutation);
2418 if (mode == SHADERMODE_LIGHTSOURCE)
2420 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2421 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2422 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2423 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);
2424 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);
2425 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
2427 // additive passes are only darkened by fog, not tinted
2428 if (r_glsl_permutation->loc_FogColor >= 0)
2429 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2430 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]);
2431 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]);
2432 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2436 if (mode == SHADERMODE_FLATCOLOR)
2438 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
2440 else if (mode == SHADERMODE_LIGHTDIRECTION)
2442 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]);
2443 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
2444 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);
2445 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);
2446 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);
2447 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]);
2448 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]);
2452 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]);
2453 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]);
2454 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);
2455 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);
2456 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);
2458 // additive passes are only darkened by fog, not tinted
2459 if (r_glsl_permutation->loc_FogColor >= 0)
2461 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2462 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2464 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2466 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);
2467 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]);
2468 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]);
2469 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2470 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2471 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2472 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2473 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2475 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2476 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2477 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2478 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
2479 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2480 if (r_glsl_permutation->loc_Color_Pants >= 0)
2482 if (rsurface.texture->currentskinframe->pants)
2483 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2485 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2487 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2489 if (rsurface.texture->currentskinframe->shirt)
2490 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2492 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2494 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]);
2495 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2496 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2497 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2498 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2499 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]);
2503 void R_SetupDeferredLightShader(const rtlight_t *rtlight)
2505 // select a permutation of the lighting shader appropriate to this
2506 // combination of texture, entity, light source, and fogging, only use the
2507 // minimum features necessary to avoid wasting rendering time in the
2508 // fragment shader on features that are not being used
2509 unsigned int permutation = 0;
2510 unsigned int mode = 0;
2511 const float *lightcolorbase = rtlight->currentcolor;
2512 float ambientscale = rtlight->ambientscale;
2513 float diffusescale = rtlight->diffusescale;
2514 float specularscale = rtlight->specularscale;
2515 // this is the location of the light in view space
2516 vec3_t viewlightorigin;
2517 // this transforms from view space (camera) to light space (cubemap)
2518 matrix4x4_t viewtolight;
2519 matrix4x4_t lighttoview;
2520 float viewtolight16f[16];
2521 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2523 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2524 if (rtlight->currentcubemap != r_texture_whitecube)
2525 permutation |= SHADERPERMUTATION_CUBEFILTER;
2526 if (diffusescale > 0)
2527 permutation |= SHADERPERMUTATION_DIFFUSE;
2528 if (specularscale > 0)
2530 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2531 if (r_shadow_glossexact.integer)
2532 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2534 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2536 if (r_shadow_usingshadowmaprect)
2537 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2538 if (r_shadow_usingshadowmap2d)
2539 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2540 if (r_shadow_usingshadowmapcube)
2541 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2542 else if(r_shadow_shadowmapvsdct)
2543 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2545 if (r_shadow_shadowmapsampler)
2546 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2547 if (r_shadow_shadowmappcf > 1)
2548 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2549 else if (r_shadow_shadowmappcf)
2550 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2552 R_SetupShader_SetPermutation(mode, permutation);
2553 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2554 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2555 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2556 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2557 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2558 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight, 1, false, viewtolight16f);
2559 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);
2560 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);
2561 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);
2562 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]);
2563 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]);
2564 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));
2565 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]);
2568 #define SKINFRAME_HASH 1024
2572 int loadsequence; // incremented each level change
2573 memexpandablearray_t array;
2574 skinframe_t *hash[SKINFRAME_HASH];
2577 r_skinframe_t r_skinframe;
2579 void R_SkinFrame_PrepareForPurge(void)
2581 r_skinframe.loadsequence++;
2582 // wrap it without hitting zero
2583 if (r_skinframe.loadsequence >= 200)
2584 r_skinframe.loadsequence = 1;
2587 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2591 // mark the skinframe as used for the purging code
2592 skinframe->loadsequence = r_skinframe.loadsequence;
2595 void R_SkinFrame_Purge(void)
2599 for (i = 0;i < SKINFRAME_HASH;i++)
2601 for (s = r_skinframe.hash[i];s;s = s->next)
2603 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2605 if (s->merged == s->base)
2607 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2608 R_PurgeTexture(s->stain );s->stain = NULL;
2609 R_PurgeTexture(s->merged);s->merged = NULL;
2610 R_PurgeTexture(s->base );s->base = NULL;
2611 R_PurgeTexture(s->pants );s->pants = NULL;
2612 R_PurgeTexture(s->shirt );s->shirt = NULL;
2613 R_PurgeTexture(s->nmap );s->nmap = NULL;
2614 R_PurgeTexture(s->gloss );s->gloss = NULL;
2615 R_PurgeTexture(s->glow );s->glow = NULL;
2616 R_PurgeTexture(s->fog );s->fog = NULL;
2617 s->loadsequence = 0;
2623 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2625 char basename[MAX_QPATH];
2627 Image_StripImageExtension(name, basename, sizeof(basename));
2629 if( last == NULL ) {
2631 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2632 item = r_skinframe.hash[hashindex];
2637 // linearly search through the hash bucket
2638 for( ; item ; item = item->next ) {
2639 if( !strcmp( item->basename, basename ) ) {
2646 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2650 char basename[MAX_QPATH];
2652 Image_StripImageExtension(name, basename, sizeof(basename));
2654 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2655 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2656 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2660 rtexture_t *dyntexture;
2661 // check whether its a dynamic texture
2662 dyntexture = CL_GetDynTexture( basename );
2663 if (!add && !dyntexture)
2665 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2666 memset(item, 0, sizeof(*item));
2667 strlcpy(item->basename, basename, sizeof(item->basename));
2668 item->base = dyntexture; // either NULL or dyntexture handle
2669 item->textureflags = textureflags;
2670 item->comparewidth = comparewidth;
2671 item->compareheight = compareheight;
2672 item->comparecrc = comparecrc;
2673 item->next = r_skinframe.hash[hashindex];
2674 r_skinframe.hash[hashindex] = item;
2676 else if( item->base == NULL )
2678 rtexture_t *dyntexture;
2679 // check whether its a dynamic texture
2680 // 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]
2681 dyntexture = CL_GetDynTexture( basename );
2682 item->base = dyntexture; // either NULL or dyntexture handle
2685 R_SkinFrame_MarkUsed(item);
2689 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2691 unsigned long long avgcolor[5], wsum; \
2699 for(pix = 0; pix < cnt; ++pix) \
2702 for(comp = 0; comp < 3; ++comp) \
2704 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2707 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2709 for(comp = 0; comp < 3; ++comp) \
2710 avgcolor[comp] += getpixel * w; \
2713 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2714 avgcolor[4] += getpixel; \
2716 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2718 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2719 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2720 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2721 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2724 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2727 unsigned char *pixels;
2728 unsigned char *bumppixels;
2729 unsigned char *basepixels = NULL;
2730 int basepixels_width;
2731 int basepixels_height;
2732 skinframe_t *skinframe;
2734 if (cls.state == ca_dedicated)
2737 // return an existing skinframe if already loaded
2738 // if loading of the first image fails, don't make a new skinframe as it
2739 // would cause all future lookups of this to be missing
2740 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2741 if (skinframe && skinframe->base)
2744 basepixels = loadimagepixelsbgra(name, complain, true);
2745 if (basepixels == NULL)
2748 if (developer_loading.integer)
2749 Con_Printf("loading skin \"%s\"\n", name);
2751 // we've got some pixels to store, so really allocate this new texture now
2753 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2754 skinframe->stain = NULL;
2755 skinframe->merged = NULL;
2756 skinframe->base = r_texture_notexture;
2757 skinframe->pants = NULL;
2758 skinframe->shirt = NULL;
2759 skinframe->nmap = r_texture_blanknormalmap;
2760 skinframe->gloss = NULL;
2761 skinframe->glow = NULL;
2762 skinframe->fog = NULL;
2763 skinframe->hasalpha = false;
2765 basepixels_width = image_width;
2766 basepixels_height = image_height;
2767 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);
2769 if (textureflags & TEXF_ALPHA)
2771 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2773 if (basepixels[j] < 255)
2775 skinframe->hasalpha = true;
2779 if (r_loadfog && skinframe->hasalpha)
2781 // has transparent pixels
2782 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2783 for (j = 0;j < image_width * image_height * 4;j += 4)
2788 pixels[j+3] = basepixels[j+3];
2790 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);
2795 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2796 //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]);
2798 // _norm is the name used by tenebrae and has been adopted as standard
2799 if (r_loadnormalmap)
2801 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2803 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);
2807 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2809 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2810 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2811 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);
2813 Mem_Free(bumppixels);
2815 else if (r_shadow_bumpscale_basetexture.value > 0)
2817 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2818 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2819 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);
2823 // _luma is supported for tenebrae compatibility
2824 // (I think it's a very stupid name, but oh well)
2825 // _glow is the preferred name
2826 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;}
2827 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;}
2828 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;}
2829 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;}
2832 Mem_Free(basepixels);
2837 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2838 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2841 unsigned char *temp1, *temp2;
2842 skinframe_t *skinframe;
2844 if (cls.state == ca_dedicated)
2847 // if already loaded just return it, otherwise make a new skinframe
2848 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2849 if (skinframe && skinframe->base)
2852 skinframe->stain = NULL;
2853 skinframe->merged = NULL;
2854 skinframe->base = r_texture_notexture;
2855 skinframe->pants = NULL;
2856 skinframe->shirt = NULL;
2857 skinframe->nmap = r_texture_blanknormalmap;
2858 skinframe->gloss = NULL;
2859 skinframe->glow = NULL;
2860 skinframe->fog = NULL;
2861 skinframe->hasalpha = false;
2863 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2867 if (developer_loading.integer)
2868 Con_Printf("loading 32bit skin \"%s\"\n", name);
2870 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2872 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2873 temp2 = temp1 + width * height * 4;
2874 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2875 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2878 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2879 if (textureflags & TEXF_ALPHA)
2881 for (i = 3;i < width * height * 4;i += 4)
2883 if (skindata[i] < 255)
2885 skinframe->hasalpha = true;
2889 if (r_loadfog && skinframe->hasalpha)
2891 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2892 memcpy(fogpixels, skindata, width * height * 4);
2893 for (i = 0;i < width * height * 4;i += 4)
2894 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2895 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2896 Mem_Free(fogpixels);
2900 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2901 //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]);
2906 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2910 skinframe_t *skinframe;
2912 if (cls.state == ca_dedicated)
2915 // if already loaded just return it, otherwise make a new skinframe
2916 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2917 if (skinframe && skinframe->base)
2920 skinframe->stain = NULL;
2921 skinframe->merged = NULL;
2922 skinframe->base = r_texture_notexture;
2923 skinframe->pants = NULL;
2924 skinframe->shirt = NULL;
2925 skinframe->nmap = r_texture_blanknormalmap;
2926 skinframe->gloss = NULL;
2927 skinframe->glow = NULL;
2928 skinframe->fog = NULL;
2929 skinframe->hasalpha = false;
2931 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2935 if (developer_loading.integer)
2936 Con_Printf("loading quake skin \"%s\"\n", name);
2938 // 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)
2939 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
2940 memcpy(skinframe->qpixels, skindata, width*height);
2941 skinframe->qwidth = width;
2942 skinframe->qheight = height;
2945 for (i = 0;i < width * height;i++)
2946 featuresmask |= palette_featureflags[skindata[i]];
2948 skinframe->hasalpha = false;
2949 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2950 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2951 skinframe->qgeneratemerged = true;
2952 skinframe->qgeneratebase = skinframe->qhascolormapping;
2953 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2955 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2956 //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]);
2961 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2965 unsigned char *skindata;
2967 if (!skinframe->qpixels)
2970 if (!skinframe->qhascolormapping)
2971 colormapped = false;
2975 if (!skinframe->qgeneratebase)
2980 if (!skinframe->qgeneratemerged)
2984 width = skinframe->qwidth;
2985 height = skinframe->qheight;
2986 skindata = skinframe->qpixels;
2988 if (skinframe->qgeneratenmap)
2990 unsigned char *temp1, *temp2;
2991 skinframe->qgeneratenmap = false;
2992 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2993 temp2 = temp1 + width * height * 4;
2994 // use either a custom palette or the quake palette
2995 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2996 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2997 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3001 if (skinframe->qgenerateglow)
3003 skinframe->qgenerateglow = false;
3004 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
3009 skinframe->qgeneratebase = false;
3010 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);
3011 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
3012 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
3016 skinframe->qgeneratemerged = false;
3017 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3020 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3022 Mem_Free(skinframe->qpixels);
3023 skinframe->qpixels = NULL;
3027 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)
3030 skinframe_t *skinframe;
3032 if (cls.state == ca_dedicated)
3035 // if already loaded just return it, otherwise make a new skinframe
3036 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3037 if (skinframe && skinframe->base)
3040 skinframe->stain = NULL;
3041 skinframe->merged = NULL;
3042 skinframe->base = r_texture_notexture;
3043 skinframe->pants = NULL;
3044 skinframe->shirt = NULL;
3045 skinframe->nmap = r_texture_blanknormalmap;
3046 skinframe->gloss = NULL;
3047 skinframe->glow = NULL;
3048 skinframe->fog = NULL;
3049 skinframe->hasalpha = false;
3051 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3055 if (developer_loading.integer)
3056 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3058 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3059 if (textureflags & TEXF_ALPHA)
3061 for (i = 0;i < width * height;i++)
3063 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3065 skinframe->hasalpha = true;
3069 if (r_loadfog && skinframe->hasalpha)
3070 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3073 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3074 //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]);
3079 skinframe_t *R_SkinFrame_LoadMissing(void)
3081 skinframe_t *skinframe;
3083 if (cls.state == ca_dedicated)
3086 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3087 skinframe->stain = NULL;
3088 skinframe->merged = NULL;
3089 skinframe->base = r_texture_notexture;
3090 skinframe->pants = NULL;
3091 skinframe->shirt = NULL;
3092 skinframe->nmap = r_texture_blanknormalmap;
3093 skinframe->gloss = NULL;
3094 skinframe->glow = NULL;
3095 skinframe->fog = NULL;
3096 skinframe->hasalpha = false;
3098 skinframe->avgcolor[0] = rand() / RAND_MAX;
3099 skinframe->avgcolor[1] = rand() / RAND_MAX;
3100 skinframe->avgcolor[2] = rand() / RAND_MAX;
3101 skinframe->avgcolor[3] = 1;
3106 void R_Main_FreeViewCache(void)
3108 if (r_refdef.viewcache.entityvisible)
3109 Mem_Free(r_refdef.viewcache.entityvisible);
3110 if (r_refdef.viewcache.world_pvsbits)
3111 Mem_Free(r_refdef.viewcache.world_pvsbits);
3112 if (r_refdef.viewcache.world_leafvisible)
3113 Mem_Free(r_refdef.viewcache.world_leafvisible);
3114 if (r_refdef.viewcache.world_surfacevisible)
3115 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3116 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3119 void R_Main_ResizeViewCache(void)
3121 int numentities = r_refdef.scene.numentities;
3122 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3123 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3124 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3125 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3126 if (r_refdef.viewcache.maxentities < numentities)
3128 r_refdef.viewcache.maxentities = numentities;
3129 if (r_refdef.viewcache.entityvisible)
3130 Mem_Free(r_refdef.viewcache.entityvisible);
3131 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3133 if (r_refdef.viewcache.world_numclusters != numclusters)
3135 r_refdef.viewcache.world_numclusters = numclusters;
3136 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3137 if (r_refdef.viewcache.world_pvsbits)
3138 Mem_Free(r_refdef.viewcache.world_pvsbits);
3139 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3141 if (r_refdef.viewcache.world_numleafs != numleafs)
3143 r_refdef.viewcache.world_numleafs = numleafs;
3144 if (r_refdef.viewcache.world_leafvisible)
3145 Mem_Free(r_refdef.viewcache.world_leafvisible);
3146 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3148 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3150 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3151 if (r_refdef.viewcache.world_surfacevisible)
3152 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3153 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3157 extern rtexture_t *loadingscreentexture;
3158 void gl_main_start(void)
3160 loadingscreentexture = NULL;
3161 r_texture_blanknormalmap = NULL;
3162 r_texture_white = NULL;
3163 r_texture_grey128 = NULL;
3164 r_texture_black = NULL;
3165 r_texture_whitecube = NULL;
3166 r_texture_normalizationcube = NULL;
3167 r_texture_fogattenuation = NULL;
3168 r_texture_gammaramps = NULL;
3170 switch(vid.renderpath)
3172 case RENDERPATH_GL20:
3173 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3174 Cvar_SetValueQuick(&gl_combine, 1);
3175 Cvar_SetValueQuick(&r_glsl, 1);
3176 r_loadnormalmap = true;
3180 case RENDERPATH_GL13:
3181 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3182 Cvar_SetValueQuick(&gl_combine, 1);
3183 Cvar_SetValueQuick(&r_glsl, 0);
3184 r_loadnormalmap = false;
3185 r_loadgloss = false;
3188 case RENDERPATH_GL11:
3189 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3190 Cvar_SetValueQuick(&gl_combine, 0);
3191 Cvar_SetValueQuick(&r_glsl, 0);
3192 r_loadnormalmap = false;
3193 r_loadgloss = false;
3199 R_FrameData_Reset();
3203 memset(r_queries, 0, sizeof(r_queries));
3205 r_qwskincache = NULL;
3206 r_qwskincache_size = 0;
3208 // set up r_skinframe loading system for textures
3209 memset(&r_skinframe, 0, sizeof(r_skinframe));
3210 r_skinframe.loadsequence = 1;
3211 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3213 r_main_texturepool = R_AllocTexturePool();
3214 R_BuildBlankTextures();
3216 if (vid.support.arb_texture_cube_map)
3219 R_BuildNormalizationCube();
3221 r_texture_fogattenuation = NULL;
3222 r_texture_gammaramps = NULL;
3223 //r_texture_fogintensity = NULL;
3224 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3225 memset(&r_waterstate, 0, sizeof(r_waterstate));
3226 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3227 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3228 memset(&r_svbsp, 0, sizeof (r_svbsp));
3230 r_refdef.fogmasktable_density = 0;
3233 void gl_main_shutdown(void)
3236 R_FrameData_Reset();
3238 R_Main_FreeViewCache();
3241 qglDeleteQueriesARB(r_maxqueries, r_queries);
3245 memset(r_queries, 0, sizeof(r_queries));
3247 r_qwskincache = NULL;
3248 r_qwskincache_size = 0;
3250 // clear out the r_skinframe state
3251 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3252 memset(&r_skinframe, 0, sizeof(r_skinframe));
3255 Mem_Free(r_svbsp.nodes);
3256 memset(&r_svbsp, 0, sizeof (r_svbsp));
3257 R_FreeTexturePool(&r_main_texturepool);
3258 loadingscreentexture = NULL;
3259 r_texture_blanknormalmap = NULL;
3260 r_texture_white = NULL;
3261 r_texture_grey128 = NULL;
3262 r_texture_black = NULL;
3263 r_texture_whitecube = NULL;
3264 r_texture_normalizationcube = NULL;
3265 r_texture_fogattenuation = NULL;
3266 r_texture_gammaramps = NULL;
3267 //r_texture_fogintensity = NULL;
3268 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3269 memset(&r_waterstate, 0, sizeof(r_waterstate));
3273 extern void CL_ParseEntityLump(char *entitystring);
3274 void gl_main_newmap(void)
3276 // FIXME: move this code to client
3278 char *entities, entname[MAX_QPATH];
3280 Mem_Free(r_qwskincache);
3281 r_qwskincache = NULL;
3282 r_qwskincache_size = 0;
3285 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
3286 l = (int)strlen(entname) - 4;
3287 if (l >= 0 && !strcmp(entname + l, ".bsp"))
3289 memcpy(entname + l, ".ent", 5);
3290 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3292 CL_ParseEntityLump(entities);
3297 if (cl.worldmodel->brush.entities)
3298 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3300 R_Main_FreeViewCache();
3302 R_FrameData_Reset();
3305 void GL_Main_Init(void)
3307 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3309 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3310 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3311 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3312 if (gamemode == GAME_NEHAHRA)
3314 Cvar_RegisterVariable (&gl_fogenable);
3315 Cvar_RegisterVariable (&gl_fogdensity);
3316 Cvar_RegisterVariable (&gl_fogred);
3317 Cvar_RegisterVariable (&gl_foggreen);
3318 Cvar_RegisterVariable (&gl_fogblue);
3319 Cvar_RegisterVariable (&gl_fogstart);
3320 Cvar_RegisterVariable (&gl_fogend);
3321 Cvar_RegisterVariable (&gl_skyclip);
3323 Cvar_RegisterVariable(&r_motionblur);
3324 Cvar_RegisterVariable(&r_motionblur_maxblur);
3325 Cvar_RegisterVariable(&r_motionblur_bmin);
3326 Cvar_RegisterVariable(&r_motionblur_vmin);
3327 Cvar_RegisterVariable(&r_motionblur_vmax);
3328 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3329 Cvar_RegisterVariable(&r_motionblur_randomize);
3330 Cvar_RegisterVariable(&r_damageblur);
3331 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3332 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3333 Cvar_RegisterVariable(&r_equalize_entities_by);
3334 Cvar_RegisterVariable(&r_equalize_entities_to);
3335 Cvar_RegisterVariable(&r_depthfirst);
3336 Cvar_RegisterVariable(&r_useinfinitefarclip);
3337 Cvar_RegisterVariable(&r_farclip_base);
3338 Cvar_RegisterVariable(&r_farclip_world);
3339 Cvar_RegisterVariable(&r_nearclip);
3340 Cvar_RegisterVariable(&r_showbboxes);
3341 Cvar_RegisterVariable(&r_showsurfaces);
3342 Cvar_RegisterVariable(&r_showtris);
3343 Cvar_RegisterVariable(&r_shownormals);
3344 Cvar_RegisterVariable(&r_showlighting);
3345 Cvar_RegisterVariable(&r_showshadowvolumes);
3346 Cvar_RegisterVariable(&r_showcollisionbrushes);
3347 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3348 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3349 Cvar_RegisterVariable(&r_showdisabledepthtest);
3350 Cvar_RegisterVariable(&r_drawportals);
3351 Cvar_RegisterVariable(&r_drawentities);
3352 Cvar_RegisterVariable(&r_cullentities_trace);
3353 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3354 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3355 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3356 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3357 Cvar_RegisterVariable(&r_drawviewmodel);
3358 Cvar_RegisterVariable(&r_speeds);
3359 Cvar_RegisterVariable(&r_fullbrights);
3360 Cvar_RegisterVariable(&r_wateralpha);
3361 Cvar_RegisterVariable(&r_dynamic);
3362 Cvar_RegisterVariable(&r_fullbright);
3363 Cvar_RegisterVariable(&r_shadows);
3364 Cvar_RegisterVariable(&r_shadows_darken);
3365 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3366 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3367 Cvar_RegisterVariable(&r_shadows_throwdistance);
3368 Cvar_RegisterVariable(&r_shadows_throwdirection);
3369 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3370 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3371 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3372 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3373 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3374 Cvar_RegisterVariable(&r_fog_exp2);
3375 Cvar_RegisterVariable(&r_drawfog);
3376 Cvar_RegisterVariable(&r_transparentdepthmasking);
3377 Cvar_RegisterVariable(&r_textureunits);
3378 Cvar_RegisterVariable(&gl_combine);
3379 Cvar_RegisterVariable(&r_glsl);
3380 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3381 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3382 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3383 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3384 Cvar_RegisterVariable(&r_glsl_postprocess);
3385 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3386 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3387 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3388 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3389 Cvar_RegisterVariable(&r_water);
3390 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3391 Cvar_RegisterVariable(&r_water_clippingplanebias);
3392 Cvar_RegisterVariable(&r_water_refractdistort);
3393 Cvar_RegisterVariable(&r_water_reflectdistort);
3394 Cvar_RegisterVariable(&r_lerpsprites);
3395 Cvar_RegisterVariable(&r_lerpmodels);
3396 Cvar_RegisterVariable(&r_lerplightstyles);
3397 Cvar_RegisterVariable(&r_waterscroll);
3398 Cvar_RegisterVariable(&r_bloom);
3399 Cvar_RegisterVariable(&r_bloom_colorscale);
3400 Cvar_RegisterVariable(&r_bloom_brighten);
3401 Cvar_RegisterVariable(&r_bloom_blur);
3402 Cvar_RegisterVariable(&r_bloom_resolution);
3403 Cvar_RegisterVariable(&r_bloom_colorexponent);
3404 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3405 Cvar_RegisterVariable(&r_hdr);
3406 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3407 Cvar_RegisterVariable(&r_hdr_glowintensity);
3408 Cvar_RegisterVariable(&r_hdr_range);
3409 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3410 Cvar_RegisterVariable(&developer_texturelogging);
3411 Cvar_RegisterVariable(&gl_lightmaps);
3412 Cvar_RegisterVariable(&r_test);
3413 Cvar_RegisterVariable(&r_batchmode);
3414 Cvar_RegisterVariable(&r_glsl_saturation);
3415 Cvar_RegisterVariable(&r_framedatasize);
3416 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3417 Cvar_SetValue("r_fullbrights", 0);
3418 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3420 Cvar_RegisterVariable(&r_track_sprites);
3421 Cvar_RegisterVariable(&r_track_sprites_flags);
3422 Cvar_RegisterVariable(&r_track_sprites_scalew);
3423 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3426 extern void R_Textures_Init(void);
3427 extern void GL_Draw_Init(void);
3428 extern void GL_Main_Init(void);
3429 extern void R_Shadow_Init(void);
3430 extern void R_Sky_Init(void);
3431 extern void GL_Surf_Init(void);
3432 extern void R_Particles_Init(void);
3433 extern void R_Explosion_Init(void);
3434 extern void gl_backend_init(void);
3435 extern void Sbar_Init(void);
3436 extern void R_LightningBeams_Init(void);
3437 extern void Mod_RenderInit(void);
3439 void Render_Init(void)
3451 R_LightningBeams_Init();
3460 extern char *ENGINE_EXTENSIONS;
3463 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3464 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3465 gl_version = (const char *)qglGetString(GL_VERSION);
3466 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3470 if (!gl_platformextensions)
3471 gl_platformextensions = "";
3473 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3474 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3475 Con_Printf("GL_VERSION: %s\n", gl_version);
3476 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3477 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3479 VID_CheckExtensions();
3481 // LordHavoc: report supported extensions
3482 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3484 // clear to black (loading plaque will be seen over this)
3486 qglClearColor(0,0,0,1);CHECKGLERROR
3487 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3490 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3494 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3496 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3499 p = r_refdef.view.frustum + i;
3504 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3508 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3512 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3516 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3520 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3524 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3528 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3532 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3540 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3544 for (i = 0;i < numplanes;i++)
3551 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3555 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3559 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3563 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3567 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3571 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3575 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3579 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3587 //==================================================================================
3589 // LordHavoc: this stores temporary data used within the same frame
3591 qboolean r_framedata_failed;
3592 static size_t r_framedata_size;
3593 static size_t r_framedata_current;
3594 static void *r_framedata_base;
3596 void R_FrameData_Reset(void)
3598 if (r_framedata_base);
3599 Mem_Free(r_framedata_base);
3600 r_framedata_base = NULL;
3601 r_framedata_size = 0;
3602 r_framedata_current = 0;
3603 r_framedata_failed = false;
3606 void R_FrameData_NewFrame(void)
3609 if (r_framedata_failed)
3610 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
3611 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
3612 wantedsize = bound(65536, wantedsize, 128*1024*1024);
3613 if (r_framedata_size != wantedsize)
3615 r_framedata_size = wantedsize;
3616 if (r_framedata_base);
3617 Mem_Free(r_framedata_base);
3618 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
3620 r_framedata_current = 0;
3621 r_framedata_failed = false;
3624 void *R_FrameData_Alloc(size_t size)
3628 // align to 16 byte boundary
3629 size = (size + 15) & ~15;
3630 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
3631 r_framedata_current += size;
3634 if (r_framedata_current > r_framedata_size)
3635 r_framedata_failed = true;
3637 // return NULL on everything after a failure
3638 if (r_framedata_failed)
3644 void *R_FrameData_Store(size_t size, void *data)
3646 void *d = R_FrameData_Alloc(size);
3648 memcpy(d, data, size);
3652 //==================================================================================
3654 // LordHavoc: animcache originally written by Echon, rewritten since then
3657 * Animation cache prevents re-generating mesh data for an animated model
3658 * multiple times in one frame for lighting, shadowing, reflections, etc.
3661 void R_AnimCache_Free(void)
3665 void R_AnimCache_ClearCache(void)
3668 entity_render_t *ent;
3670 for (i = 0;i < r_refdef.scene.numentities;i++)
3672 ent = r_refdef.scene.entities[i];
3673 ent->animcache_vertex3f = NULL;
3674 ent->animcache_normal3f = NULL;
3675 ent->animcache_svector3f = NULL;
3676 ent->animcache_tvector3f = NULL;
3680 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3682 dp_model_t *model = ent->model;
3684 // see if it's already cached this frame
3685 if (ent->animcache_vertex3f)
3687 // add normals/tangents if needed
3688 if (wantnormals || wanttangents)
3690 if (ent->animcache_normal3f)
3691 wantnormals = false;
3692 if (ent->animcache_svector3f)
3693 wanttangents = false;
3694 if (wantnormals || wanttangents)
3696 numvertices = model->surfmesh.num_vertices;
3698 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3701 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3702 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3704 if (!r_framedata_failed)
3705 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
3711 // see if this ent is worth caching
3712 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
3714 // get some memory for this entity and generate mesh data
3715 numvertices = model->surfmesh.num_vertices;
3716 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3718 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3721 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3722 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3724 if (!r_framedata_failed)
3725 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
3727 return !r_framedata_failed;
3730 void R_AnimCache_CacheVisibleEntities(void)
3733 qboolean wantnormals = !r_showsurfaces.integer;
3734 qboolean wanttangents = !r_showsurfaces.integer;
3736 switch(vid.renderpath)
3738 case RENDERPATH_GL20:
3740 case RENDERPATH_GL13:
3741 case RENDERPATH_GL11:
3742 wanttangents = false;
3746 // TODO: thread this
3747 // NOTE: R_PrepareRTLights() also caches entities
3749 for (i = 0;i < r_refdef.scene.numentities;i++)
3750 if (r_refdef.viewcache.entityvisible[i])
3751 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3753 if (r_shadows.integer)
3754 for (i = 0;i < r_refdef.scene.numentities;i++)
3755 if (!r_refdef.viewcache.entityvisible[i])
3756 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
3759 //==================================================================================
3761 static void R_View_UpdateEntityLighting (void)
3764 entity_render_t *ent;
3765 vec3_t tempdiffusenormal, avg;
3766 vec_t f, fa, fd, fdd;
3768 for (i = 0;i < r_refdef.scene.numentities;i++)
3770 ent = r_refdef.scene.entities[i];
3772 // skip unseen models
3773 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3777 if (ent->model && ent->model->brush.num_leafs)
3779 // TODO: use modellight for r_ambient settings on world?
3780 VectorSet(ent->modellight_ambient, 0, 0, 0);
3781 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3782 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3786 // fetch the lighting from the worldmodel data
3787 VectorClear(ent->modellight_ambient);
3788 VectorClear(ent->modellight_diffuse);
3789 VectorClear(tempdiffusenormal);
3790 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3793 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3794 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3795 if(ent->flags & RENDER_EQUALIZE)
3797 // first fix up ambient lighting...
3798 if(r_equalize_entities_minambient.value > 0)
3800 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3803 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3804 if(fa < r_equalize_entities_minambient.value * fd)
3807 // fa'/fd' = minambient
3808 // fa'+0.25*fd' = fa+0.25*fd
3810 // fa' = fd' * minambient
3811 // fd'*(0.25+minambient) = fa+0.25*fd
3813 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3814 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3816 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3817 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
3818 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3819 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3824 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3826 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3827 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3830 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3831 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3832 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3838 VectorSet(ent->modellight_ambient, 1, 1, 1);
3840 // move the light direction into modelspace coordinates for lighting code
3841 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3842 if(VectorLength2(ent->modellight_lightdir) == 0)
3843 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3844 VectorNormalize(ent->modellight_lightdir);
3848 #define MAX_LINEOFSIGHTTRACES 64
3850 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3853 vec3_t boxmins, boxmaxs;
3856 dp_model_t *model = r_refdef.scene.worldmodel;
3858 if (!model || !model->brush.TraceLineOfSight)
3861 // expand the box a little
3862 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3863 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3864 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3865 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3866 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3867 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3870 VectorCopy(eye, start);
3871 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3872 if (model->brush.TraceLineOfSight(model, start, end))
3875 // try various random positions
3876 for (i = 0;i < numsamples;i++)
3878 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3879 if (model->brush.TraceLineOfSight(model, start, end))
3887 static void R_View_UpdateEntityVisible (void)
3892 entity_render_t *ent;
3894 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3895 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3897 // worldmodel can check visibility
3898 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3899 for (i = 0;i < r_refdef.scene.numentities;i++)
3901 ent = r_refdef.scene.entities[i];
3902 if (!(ent->flags & renderimask))
3903 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)))
3904 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))
3905 r_refdef.viewcache.entityvisible[i] = true;
3907 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3909 for (i = 0;i < r_refdef.scene.numentities;i++)
3911 ent = r_refdef.scene.entities[i];
3912 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3914 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3916 continue; // temp entities do pvs only
3917 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3918 ent->last_trace_visibility = realtime;
3919 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3920 r_refdef.viewcache.entityvisible[i] = 0;
3927 // no worldmodel or it can't check visibility
3928 for (i = 0;i < r_refdef.scene.numentities;i++)
3930 ent = r_refdef.scene.entities[i];
3931 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));
3936 /// only used if skyrendermasked, and normally returns false
3937 int R_DrawBrushModelsSky (void)
3940 entity_render_t *ent;
3943 for (i = 0;i < r_refdef.scene.numentities;i++)
3945 if (!r_refdef.viewcache.entityvisible[i])
3947 ent = r_refdef.scene.entities[i];
3948 if (!ent->model || !ent->model->DrawSky)
3950 ent->model->DrawSky(ent);
3956 static void R_DrawNoModel(entity_render_t *ent);
3957 static void R_DrawModels(void)
3960 entity_render_t *ent;
3962 for (i = 0;i < r_refdef.scene.numentities;i++)
3964 if (!r_refdef.viewcache.entityvisible[i])
3966 ent = r_refdef.scene.entities[i];
3967 r_refdef.stats.entities++;
3968 if (ent->model && ent->model->Draw != NULL)
3969 ent->model->Draw(ent);
3975 static void R_DrawModelsDepth(void)
3978 entity_render_t *ent;
3980 for (i = 0;i < r_refdef.scene.numentities;i++)
3982 if (!r_refdef.viewcache.entityvisible[i])
3984 ent = r_refdef.scene.entities[i];
3985 if (ent->model && ent->model->DrawDepth != NULL)
3986 ent->model->DrawDepth(ent);
3990 static void R_DrawModelsDebug(void)
3993 entity_render_t *ent;
3995 for (i = 0;i < r_refdef.scene.numentities;i++)
3997 if (!r_refdef.viewcache.entityvisible[i])
3999 ent = r_refdef.scene.entities[i];
4000 if (ent->model && ent->model->DrawDebug != NULL)
4001 ent->model->DrawDebug(ent);
4005 static void R_DrawModelsAddWaterPlanes(void)
4008 entity_render_t *ent;
4010 for (i = 0;i < r_refdef.scene.numentities;i++)
4012 if (!r_refdef.viewcache.entityvisible[i])
4014 ent = r_refdef.scene.entities[i];
4015 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4016 ent->model->DrawAddWaterPlanes(ent);
4020 static void R_View_SetFrustum(void)
4023 double slopex, slopey;
4024 vec3_t forward, left, up, origin;
4026 // we can't trust r_refdef.view.forward and friends in reflected scenes
4027 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4030 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4031 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4032 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4033 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4034 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4035 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4036 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4037 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4038 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4039 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4040 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4041 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4045 zNear = r_refdef.nearclip;
4046 nudge = 1.0 - 1.0 / (1<<23);
4047 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4048 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4049 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4050 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4051 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4052 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4053 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4054 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4060 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4061 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4062 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4063 r_refdef.view.frustum[0].dist = m[15] - m[12];
4065 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4066 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4067 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4068 r_refdef.view.frustum[1].dist = m[15] + m[12];
4070 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4071 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4072 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4073 r_refdef.view.frustum[2].dist = m[15] - m[13];
4075 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4076 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4077 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4078 r_refdef.view.frustum[3].dist = m[15] + m[13];
4080 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4081 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4082 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4083 r_refdef.view.frustum[4].dist = m[15] - m[14];
4085 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4086 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4087 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4088 r_refdef.view.frustum[5].dist = m[15] + m[14];
4091 if (r_refdef.view.useperspective)
4093 slopex = 1.0 / r_refdef.view.frustum_x;
4094 slopey = 1.0 / r_refdef.view.frustum_y;
4095 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4096 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
4097 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
4098 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
4099 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4101 // Leaving those out was a mistake, those were in the old code, and they
4102 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4103 // I couldn't reproduce it after adding those normalizations. --blub
4104 VectorNormalize(r_refdef.view.frustum[0].normal);
4105 VectorNormalize(r_refdef.view.frustum[1].normal);
4106 VectorNormalize(r_refdef.view.frustum[2].normal);
4107 VectorNormalize(r_refdef.view.frustum[3].normal);
4109 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4110 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]);
4111 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]);
4112 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]);
4113 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]);
4115 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4116 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4117 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4118 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4119 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4123 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4124 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4125 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4126 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4127 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4128 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4129 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4130 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4131 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4132 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4134 r_refdef.view.numfrustumplanes = 5;
4136 if (r_refdef.view.useclipplane)
4138 r_refdef.view.numfrustumplanes = 6;
4139 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4142 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4143 PlaneClassify(r_refdef.view.frustum + i);
4145 // LordHavoc: note to all quake engine coders, Quake had a special case
4146 // for 90 degrees which assumed a square view (wrong), so I removed it,
4147 // Quake2 has it disabled as well.
4149 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4150 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4151 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4152 //PlaneClassify(&frustum[0]);
4154 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4155 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4156 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4157 //PlaneClassify(&frustum[1]);
4159 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4160 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4161 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4162 //PlaneClassify(&frustum[2]);
4164 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4165 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4166 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4167 //PlaneClassify(&frustum[3]);
4170 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4171 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4172 //PlaneClassify(&frustum[4]);
4175 void R_View_Update(void)
4177 R_Main_ResizeViewCache();
4178 R_View_SetFrustum();
4179 R_View_WorldVisibility(r_refdef.view.useclipplane);
4180 R_View_UpdateEntityVisible();
4181 R_View_UpdateEntityLighting();
4184 void R_SetupView(qboolean allowwaterclippingplane)
4186 const float *customclipplane = NULL;
4188 if (r_refdef.view.useclipplane && allowwaterclippingplane)
4190 // LordHavoc: couldn't figure out how to make this approach the
4191 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4192 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4193 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4194 dist = r_refdef.view.clipplane.dist;
4195 plane[0] = r_refdef.view.clipplane.normal[0];
4196 plane[1] = r_refdef.view.clipplane.normal[1];
4197 plane[2] = r_refdef.view.clipplane.normal[2];
4199 customclipplane = plane;
4202 if (!r_refdef.view.useperspective)
4203 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);
4204 else if (vid.stencil && r_useinfinitefarclip.integer)
4205 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);
4207 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);
4208 R_SetViewport(&r_refdef.view.viewport);
4211 void R_ResetViewRendering2D(void)
4213 r_viewport_t viewport;
4216 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4217 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);
4218 R_SetViewport(&viewport);
4219 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
4220 GL_Color(1, 1, 1, 1);
4221 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4222 GL_BlendFunc(GL_ONE, GL_ZERO);
4223 GL_AlphaTest(false);
4224 GL_ScissorTest(false);
4225 GL_DepthMask(false);
4226 GL_DepthRange(0, 1);
4227 GL_DepthTest(false);
4228 R_Mesh_Matrix(&identitymatrix);
4229 R_Mesh_ResetTextureState();
4230 GL_PolygonOffset(0, 0);
4231 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4232 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4233 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4234 qglStencilMask(~0);CHECKGLERROR
4235 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4236 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4237 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
4238 R_SetupGenericShader(true);
4241 void R_ResetViewRendering3D(void)
4246 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4247 GL_Color(1, 1, 1, 1);
4248 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4249 GL_BlendFunc(GL_ONE, GL_ZERO);
4250 GL_AlphaTest(false);
4251 GL_ScissorTest(true);
4253 GL_DepthRange(0, 1);
4255 R_Mesh_Matrix(&identitymatrix);
4256 R_Mesh_ResetTextureState();
4257 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4258 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4259 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4260 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4261 qglStencilMask(~0);CHECKGLERROR
4262 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4263 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4264 GL_CullFace(r_refdef.view.cullface_back);
4265 R_SetupGenericShader(true);
4268 void R_RenderScene(void);
4269 void R_RenderWaterPlanes(void);
4271 static void R_Water_StartFrame(void)
4274 int waterwidth, waterheight, texturewidth, textureheight;
4275 r_waterstate_waterplane_t *p;
4277 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
4280 switch(vid.renderpath)
4282 case RENDERPATH_GL20:
4284 case RENDERPATH_GL13:
4285 case RENDERPATH_GL11:
4289 // set waterwidth and waterheight to the water resolution that will be
4290 // used (often less than the screen resolution for faster rendering)
4291 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4292 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4294 // calculate desired texture sizes
4295 // can't use water if the card does not support the texture size
4296 if (!r_water.integer || r_showsurfaces.integer)
4297 texturewidth = textureheight = waterwidth = waterheight = 0;
4298 else if (vid.support.arb_texture_non_power_of_two)
4300 texturewidth = waterwidth;
4301 textureheight = waterheight;
4305 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4306 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4309 // allocate textures as needed
4310 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4312 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4313 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4315 if (p->texture_refraction)
4316 R_FreeTexture(p->texture_refraction);
4317 p->texture_refraction = NULL;
4318 if (p->texture_reflection)
4319 R_FreeTexture(p->texture_reflection);
4320 p->texture_reflection = NULL;
4322 memset(&r_waterstate, 0, sizeof(r_waterstate));
4323 r_waterstate.texturewidth = texturewidth;
4324 r_waterstate.textureheight = textureheight;
4327 if (r_waterstate.texturewidth)
4329 r_waterstate.enabled = true;
4331 // when doing a reduced render (HDR) we want to use a smaller area
4332 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4333 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4335 // set up variables that will be used in shader setup
4336 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4337 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4338 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4339 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4342 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4343 r_waterstate.numwaterplanes = 0;
4346 void R_Water_AddWaterPlane(msurface_t *surface)
4348 int triangleindex, planeindex;
4354 r_waterstate_waterplane_t *p;
4355 texture_t *t = R_GetCurrentTexture(surface->texture);
4356 // just use the first triangle with a valid normal for any decisions
4357 VectorClear(normal);
4358 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4360 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4361 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4362 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4363 TriangleNormal(vert[0], vert[1], vert[2], normal);
4364 if (VectorLength2(normal) >= 0.001)
4368 VectorCopy(normal, plane.normal);
4369 VectorNormalize(plane.normal);
4370 plane.dist = DotProduct(vert[0], plane.normal);
4371 PlaneClassify(&plane);
4372 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4374 // skip backfaces (except if nocullface is set)
4375 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4377 VectorNegate(plane.normal, plane.normal);
4379 PlaneClassify(&plane);
4383 // find a matching plane if there is one
4384 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4385 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4387 if (planeindex >= r_waterstate.maxwaterplanes)
4388 return; // nothing we can do, out of planes
4390 // if this triangle does not fit any known plane rendered this frame, add one
4391 if (planeindex >= r_waterstate.numwaterplanes)
4393 // store the new plane
4394 r_waterstate.numwaterplanes++;
4396 // clear materialflags and pvs
4397 p->materialflags = 0;
4398 p->pvsvalid = false;
4400 // merge this surface's materialflags into the waterplane
4401 p->materialflags |= t->currentmaterialflags;
4402 // merge this surface's PVS into the waterplane
4403 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4404 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4405 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4407 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4412 static void R_Water_ProcessPlanes(void)
4414 r_refdef_view_t originalview;
4415 r_refdef_view_t myview;
4417 r_waterstate_waterplane_t *p;
4419 originalview = r_refdef.view;
4421 // make sure enough textures are allocated
4422 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4424 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4426 if (!p->texture_refraction)
4427 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, NULL);
4428 if (!p->texture_refraction)
4432 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4434 if (!p->texture_reflection)
4435 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, NULL);
4436 if (!p->texture_reflection)
4442 r_refdef.view = originalview;
4443 r_refdef.view.showdebug = false;
4444 r_refdef.view.width = r_waterstate.waterwidth;
4445 r_refdef.view.height = r_waterstate.waterheight;
4446 r_refdef.view.useclipplane = true;
4447 myview = r_refdef.view;
4448 r_waterstate.renderingscene = true;
4449 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4451 // render the normal view scene and copy into texture
4452 // (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)
4453 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4455 r_refdef.view = myview;
4456 r_refdef.view.clipplane = p->plane;
4457 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4458 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4459 PlaneClassify(&r_refdef.view.clipplane);
4461 R_ResetViewRendering3D();
4462 R_ClearScreen(r_refdef.fogenabled);
4466 // copy view into the screen texture
4467 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4468 GL_ActiveTexture(0);
4470 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
4473 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4475 r_refdef.view = myview;
4476 // render reflected scene and copy into texture
4477 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4478 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4479 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4480 r_refdef.view.clipplane = p->plane;
4481 // reverse the cullface settings for this render
4482 r_refdef.view.cullface_front = GL_FRONT;
4483 r_refdef.view.cullface_back = GL_BACK;
4484 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4486 r_refdef.view.usecustompvs = true;
4488 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4490 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4493 R_ResetViewRendering3D();
4494 R_ClearScreen(r_refdef.fogenabled);
4498 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4499 GL_ActiveTexture(0);
4501 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
4504 r_waterstate.renderingscene = false;
4505 r_refdef.view = originalview;
4506 R_ResetViewRendering3D();
4507 R_ClearScreen(r_refdef.fogenabled);
4511 r_refdef.view = originalview;
4512 r_waterstate.renderingscene = false;
4513 Cvar_SetValueQuick(&r_water, 0);
4514 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4518 void R_Bloom_StartFrame(void)
4520 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4522 switch(vid.renderpath)
4524 case RENDERPATH_GL20:
4526 case RENDERPATH_GL13:
4527 case RENDERPATH_GL11:
4531 // set bloomwidth and bloomheight to the bloom resolution that will be
4532 // used (often less than the screen resolution for faster rendering)
4533 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4534 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4535 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4536 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
4537 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
4539 // calculate desired texture sizes
4540 if (vid.support.arb_texture_non_power_of_two)
4542 screentexturewidth = r_refdef.view.width;
4543 screentextureheight = r_refdef.view.height;
4544 bloomtexturewidth = r_bloomstate.bloomwidth;
4545 bloomtextureheight = r_bloomstate.bloomheight;
4549 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4550 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4551 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4552 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4555 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))
4557 Cvar_SetValueQuick(&r_hdr, 0);
4558 Cvar_SetValueQuick(&r_bloom, 0);
4559 Cvar_SetValueQuick(&r_motionblur, 0);
4560 Cvar_SetValueQuick(&r_damageblur, 0);
4563 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)))
4564 screentexturewidth = screentextureheight = 0;
4565 if (!r_hdr.integer && !r_bloom.integer)
4566 bloomtexturewidth = bloomtextureheight = 0;
4568 // allocate textures as needed
4569 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4571 if (r_bloomstate.texture_screen)
4572 R_FreeTexture(r_bloomstate.texture_screen);
4573 r_bloomstate.texture_screen = NULL;
4574 r_bloomstate.screentexturewidth = screentexturewidth;
4575 r_bloomstate.screentextureheight = screentextureheight;
4576 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4577 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
4579 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4581 if (r_bloomstate.texture_bloom)
4582 R_FreeTexture(r_bloomstate.texture_bloom);
4583 r_bloomstate.texture_bloom = NULL;
4584 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4585 r_bloomstate.bloomtextureheight = bloomtextureheight;
4586 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4587 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
4590 // when doing a reduced render (HDR) we want to use a smaller area
4591 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4592 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4593 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4594 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4595 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4597 // set up a texcoord array for the full resolution screen image
4598 // (we have to keep this around to copy back during final render)
4599 r_bloomstate.screentexcoord2f[0] = 0;
4600 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4601 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4602 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4603 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4604 r_bloomstate.screentexcoord2f[5] = 0;
4605 r_bloomstate.screentexcoord2f[6] = 0;
4606 r_bloomstate.screentexcoord2f[7] = 0;
4608 // set up a texcoord array for the reduced resolution bloom image
4609 // (which will be additive blended over the screen image)
4610 r_bloomstate.bloomtexcoord2f[0] = 0;
4611 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4612 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4613 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4614 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4615 r_bloomstate.bloomtexcoord2f[5] = 0;
4616 r_bloomstate.bloomtexcoord2f[6] = 0;
4617 r_bloomstate.bloomtexcoord2f[7] = 0;
4619 if (r_hdr.integer || r_bloom.integer)
4621 r_bloomstate.enabled = true;
4622 r_bloomstate.hdr = r_hdr.integer != 0;
4625 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);
4628 void R_Bloom_CopyBloomTexture(float colorscale)
4630 r_refdef.stats.bloom++;
4632 // scale down screen texture to the bloom texture size
4634 R_SetViewport(&r_bloomstate.viewport);
4635 GL_BlendFunc(GL_ONE, GL_ZERO);
4636 GL_Color(colorscale, colorscale, colorscale, 1);
4637 // TODO: optimize with multitexture or GLSL
4638 R_SetupGenericShader(true);
4639 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4640 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4641 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4642 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4644 // we now have a bloom image in the framebuffer
4645 // copy it into the bloom image texture for later processing
4646 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4647 GL_ActiveTexture(0);
4649 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4650 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4653 void R_Bloom_CopyHDRTexture(void)
4655 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4656 GL_ActiveTexture(0);
4658 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
4659 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4662 void R_Bloom_MakeTexture(void)
4665 float xoffset, yoffset, r, brighten;
4667 r_refdef.stats.bloom++;
4669 R_ResetViewRendering2D();
4670 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4671 R_Mesh_ColorPointer(NULL, 0, 0);
4672 R_SetupGenericShader(true);
4674 // we have a bloom image in the framebuffer
4676 R_SetViewport(&r_bloomstate.viewport);
4678 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4681 r = bound(0, r_bloom_colorexponent.value / x, 1);
4682 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4683 GL_Color(r, r, r, 1);
4684 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4685 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4686 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4687 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4689 // copy the vertically blurred bloom view to a texture
4690 GL_ActiveTexture(0);
4692 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4693 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4696 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4697 brighten = r_bloom_brighten.value;
4699 brighten *= r_hdr_range.value;
4700 brighten = sqrt(brighten);
4702 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4703 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4704 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4706 for (dir = 0;dir < 2;dir++)
4708 // blend on at multiple vertical offsets to achieve a vertical blur
4709 // TODO: do offset blends using GLSL
4710 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4711 GL_BlendFunc(GL_ONE, GL_ZERO);
4712 for (x = -range;x <= range;x++)
4714 if (!dir){xoffset = 0;yoffset = x;}
4715 else {xoffset = x;yoffset = 0;}
4716 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4717 yoffset /= (float)r_bloomstate.bloomtextureheight;
4718 // compute a texcoord array with the specified x and y offset
4719 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4720 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4721 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4722 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4723 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4724 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4725 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4726 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4727 // this r value looks like a 'dot' particle, fading sharply to
4728 // black at the edges
4729 // (probably not realistic but looks good enough)
4730 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4731 //r = brighten/(range*2+1);
4732 r = brighten / (range * 2 + 1);
4734 r *= (1 - x*x/(float)(range*range));
4735 GL_Color(r, r, r, 1);
4736 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4737 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4738 GL_BlendFunc(GL_ONE, GL_ONE);
4741 // copy the vertically blurred bloom view to a texture
4742 GL_ActiveTexture(0);
4744 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4745 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4748 // apply subtract last
4749 // (just like it would be in a GLSL shader)
4750 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
4752 GL_BlendFunc(GL_ONE, GL_ZERO);
4753 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4754 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4755 GL_Color(1, 1, 1, 1);
4756 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4757 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4759 GL_BlendFunc(GL_ONE, GL_ONE);
4760 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4761 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4762 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4763 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4764 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4765 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4766 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4768 // copy the darkened bloom view to a texture
4769 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4770 GL_ActiveTexture(0);
4772 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4773 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4777 void R_HDR_RenderBloomTexture(void)
4779 int oldwidth, oldheight;
4780 float oldcolorscale;
4782 oldcolorscale = r_refdef.view.colorscale;
4783 oldwidth = r_refdef.view.width;
4784 oldheight = r_refdef.view.height;
4785 r_refdef.view.width = r_bloomstate.bloomwidth;
4786 r_refdef.view.height = r_bloomstate.bloomheight;
4788 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4789 // TODO: add exposure compensation features
4790 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4792 r_refdef.view.showdebug = false;
4793 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4795 R_ResetViewRendering3D();
4797 R_ClearScreen(r_refdef.fogenabled);
4798 if (r_timereport_active)
4799 R_TimeReport("HDRclear");
4802 if (r_timereport_active)
4803 R_TimeReport("visibility");
4805 // only do secondary renders with HDR if r_hdr is 2 or higher
4806 r_waterstate.numwaterplanes = 0;
4807 if (r_waterstate.enabled && r_hdr.integer >= 2)
4808 R_RenderWaterPlanes();
4810 r_refdef.view.showdebug = true;
4812 r_waterstate.numwaterplanes = 0;
4814 R_ResetViewRendering2D();
4816 R_Bloom_CopyHDRTexture();
4817 R_Bloom_MakeTexture();
4819 // restore the view settings
4820 r_refdef.view.width = oldwidth;
4821 r_refdef.view.height = oldheight;
4822 r_refdef.view.colorscale = oldcolorscale;
4823 r_frame++; // used only by R_GetCurrentTexture
4825 R_ResetViewRendering3D();
4827 R_ClearScreen(r_refdef.fogenabled);
4828 if (r_timereport_active)
4829 R_TimeReport("viewclear");
4832 static void R_BlendView(void)
4834 unsigned int permutation;
4836 switch (vid.renderpath)
4838 case RENDERPATH_GL20:
4840 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4841 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4842 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4843 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4844 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4846 if (r_bloomstate.texture_screen)
4848 // make sure the buffer is available
4849 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4851 R_ResetViewRendering2D();
4852 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4853 R_Mesh_ColorPointer(NULL, 0, 0);
4854 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4855 GL_ActiveTexture(0);CHECKGLERROR
4857 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4859 // declare variables
4861 static float avgspeed;
4863 speed = VectorLength(cl.movement_velocity);
4865 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4866 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4868 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4869 speed = bound(0, speed, 1);
4870 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4872 // calculate values into a standard alpha
4873 cl.motionbluralpha = 1 - exp(-
4875 (r_motionblur.value * speed / 80)
4877 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4880 max(0.0001, cl.time - cl.oldtime) // fps independent
4883 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4884 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4886 if (cl.motionbluralpha > 0)
4888 R_SetupGenericShader(true);
4889 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4890 GL_Color(1, 1, 1, cl.motionbluralpha);
4891 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4892 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4893 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4894 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4898 // copy view into the screen texture
4899 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
4900 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4902 else if (!r_bloomstate.texture_bloom)
4904 // we may still have to do view tint...
4905 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4907 // apply a color tint to the whole view
4908 R_ResetViewRendering2D();
4909 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4910 R_Mesh_ColorPointer(NULL, 0, 0);
4911 R_SetupGenericShader(false);
4912 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4913 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4914 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4916 break; // no screen processing, no bloom, skip it
4919 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4921 // render simple bloom effect
4922 // copy the screen and shrink it and darken it for the bloom process
4923 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4924 // make the bloom texture
4925 R_Bloom_MakeTexture();
4928 R_ResetViewRendering2D();
4929 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4930 R_Mesh_ColorPointer(NULL, 0, 0);
4931 GL_Color(1, 1, 1, 1);
4932 GL_BlendFunc(GL_ONE, GL_ZERO);
4933 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4934 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4935 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4936 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4937 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4938 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4939 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4940 if (r_glsl_permutation->loc_ViewTintColor >= 0)
4941 qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4942 if (r_glsl_permutation->loc_ClientTime >= 0)
4943 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4944 if (r_glsl_permutation->loc_PixelSize >= 0)
4945 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4946 if (r_glsl_permutation->loc_UserVec1 >= 0)
4948 float a=0, b=0, c=0, d=0;
4949 #if _MSC_VER >= 1400
4950 #define sscanf sscanf_s
4952 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4953 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4955 if (r_glsl_permutation->loc_UserVec2 >= 0)
4957 float a=0, b=0, c=0, d=0;
4958 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4959 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4961 if (r_glsl_permutation->loc_UserVec3 >= 0)
4963 float a=0, b=0, c=0, d=0;
4964 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4965 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4967 if (r_glsl_permutation->loc_UserVec4 >= 0)
4969 float a=0, b=0, c=0, d=0;
4970 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4971 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4973 if (r_glsl_permutation->loc_Saturation >= 0)
4974 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4975 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4976 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4978 case RENDERPATH_GL13:
4979 case RENDERPATH_GL11:
4980 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4982 // apply a color tint to the whole view
4983 R_ResetViewRendering2D();
4984 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4985 R_Mesh_ColorPointer(NULL, 0, 0);
4986 R_SetupGenericShader(false);
4987 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4988 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4989 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4995 matrix4x4_t r_waterscrollmatrix;
4997 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4999 if (r_refdef.fog_density)
5001 r_refdef.fogcolor[0] = r_refdef.fog_red;
5002 r_refdef.fogcolor[1] = r_refdef.fog_green;
5003 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5005 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5006 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5007 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5008 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5012 VectorCopy(r_refdef.fogcolor, fogvec);
5013 // color.rgb *= ContrastBoost * SceneBrightness;
5014 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5015 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5016 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5017 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5022 void R_UpdateVariables(void)
5026 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
5028 r_refdef.farclip = r_farclip_base.value;
5029 if (r_refdef.scene.worldmodel)
5030 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5031 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5033 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5034 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5035 r_refdef.polygonfactor = 0;
5036 r_refdef.polygonoffset = 0;
5037 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5038 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5040 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5041 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5042 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5043 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5044 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5045 if (r_showsurfaces.integer)
5047 r_refdef.scene.rtworld = false;
5048 r_refdef.scene.rtworldshadows = false;
5049 r_refdef.scene.rtdlight = false;
5050 r_refdef.scene.rtdlightshadows = false;
5051 r_refdef.lightmapintensity = 0;
5054 if (gamemode == GAME_NEHAHRA)
5056 if (gl_fogenable.integer)
5058 r_refdef.oldgl_fogenable = true;
5059 r_refdef.fog_density = gl_fogdensity.value;
5060 r_refdef.fog_red = gl_fogred.value;
5061 r_refdef.fog_green = gl_foggreen.value;
5062 r_refdef.fog_blue = gl_fogblue.value;
5063 r_refdef.fog_alpha = 1;
5064 r_refdef.fog_start = 0;
5065 r_refdef.fog_end = gl_skyclip.value;
5066 r_refdef.fog_height = 1<<30;
5067 r_refdef.fog_fadedepth = 128;
5069 else if (r_refdef.oldgl_fogenable)
5071 r_refdef.oldgl_fogenable = false;
5072 r_refdef.fog_density = 0;
5073 r_refdef.fog_red = 0;
5074 r_refdef.fog_green = 0;
5075 r_refdef.fog_blue = 0;
5076 r_refdef.fog_alpha = 0;
5077 r_refdef.fog_start = 0;
5078 r_refdef.fog_end = 0;
5079 r_refdef.fog_height = 1<<30;
5080 r_refdef.fog_fadedepth = 128;
5084 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5085 r_refdef.fog_start = max(0, r_refdef.fog_start);
5086 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5088 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5090 if (r_refdef.fog_density && r_drawfog.integer)
5092 r_refdef.fogenabled = true;
5093 // this is the point where the fog reaches 0.9986 alpha, which we
5094 // consider a good enough cutoff point for the texture
5095 // (0.9986 * 256 == 255.6)
5096 if (r_fog_exp2.integer)
5097 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5099 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5100 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5101 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5102 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5103 // fog color was already set
5104 // update the fog texture
5105 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)
5106 R_BuildFogTexture();
5109 r_refdef.fogenabled = false;
5111 switch(vid.renderpath)
5113 case RENDERPATH_GL20:
5114 if(v_glslgamma.integer && !vid_gammatables_trivial)
5116 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5118 // build GLSL gamma texture
5119 #define RAMPWIDTH 256
5120 unsigned short ramp[RAMPWIDTH * 3];
5121 unsigned char rampbgr[RAMPWIDTH][4];
5124 r_texture_gammaramps_serial = vid_gammatables_serial;
5126 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5127 for(i = 0; i < RAMPWIDTH; ++i)
5129 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5130 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5131 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5134 if (r_texture_gammaramps)
5136 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5140 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
5146 // remove GLSL gamma texture
5149 case RENDERPATH_GL13:
5150 case RENDERPATH_GL11:
5155 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5156 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5162 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5163 if( scenetype != r_currentscenetype ) {
5164 // store the old scenetype
5165 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5166 r_currentscenetype = scenetype;
5167 // move in the new scene
5168 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5177 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5179 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5180 if( scenetype == r_currentscenetype ) {
5181 return &r_refdef.scene;
5183 return &r_scenes_store[ scenetype ];
5192 void R_RenderView(void)
5194 if (r_timereport_active)
5195 R_TimeReport("start");
5196 r_frame++; // used only by R_GetCurrentTexture
5197 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5199 if (!r_drawentities.integer)
5200 r_refdef.scene.numentities = 0;
5202 R_AnimCache_ClearCache();
5203 R_FrameData_NewFrame();
5205 if (r_refdef.view.isoverlay)
5207 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5208 GL_Clear( GL_DEPTH_BUFFER_BIT );
5209 R_TimeReport("depthclear");
5211 r_refdef.view.showdebug = false;
5213 r_waterstate.enabled = false;
5214 r_waterstate.numwaterplanes = 0;
5222 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
5223 return; //Host_Error ("R_RenderView: NULL worldmodel");
5225 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
5227 // break apart the view matrix into vectors for various purposes
5228 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5229 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5230 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5231 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5232 // make an inverted copy of the view matrix for tracking sprites
5233 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5235 R_Shadow_UpdateWorldLightSelection();
5237 R_Bloom_StartFrame();
5238 R_Water_StartFrame();
5241 if (r_timereport_active)
5242 R_TimeReport("viewsetup");
5244 R_ResetViewRendering3D();
5246 if (r_refdef.view.clear || r_refdef.fogenabled)
5248 R_ClearScreen(r_refdef.fogenabled);
5249 if (r_timereport_active)
5250 R_TimeReport("viewclear");
5252 r_refdef.view.clear = true;
5254 // this produces a bloom texture to be used in R_BlendView() later
5255 if (r_hdr.integer && r_bloomstate.bloomwidth)
5256 R_HDR_RenderBloomTexture();
5258 r_refdef.view.showdebug = true;
5261 if (r_timereport_active)
5262 R_TimeReport("visibility");
5264 r_waterstate.numwaterplanes = 0;
5265 if (r_waterstate.enabled)
5266 R_RenderWaterPlanes();
5269 r_waterstate.numwaterplanes = 0;
5272 if (r_timereport_active)
5273 R_TimeReport("blendview");
5275 GL_Scissor(0, 0, vid.width, vid.height);
5276 GL_ScissorTest(false);
5280 void R_RenderWaterPlanes(void)
5282 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5284 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5285 if (r_timereport_active)
5286 R_TimeReport("waterworld");
5289 // don't let sound skip if going slow
5290 if (r_refdef.scene.extraupdate)
5293 R_DrawModelsAddWaterPlanes();
5294 if (r_timereport_active)
5295 R_TimeReport("watermodels");
5297 if (r_waterstate.numwaterplanes)
5299 R_Water_ProcessPlanes();
5300 if (r_timereport_active)
5301 R_TimeReport("waterscenes");
5305 extern void R_DrawLightningBeams (void);
5306 extern void VM_CL_AddPolygonsToMeshQueue (void);
5307 extern void R_DrawPortals (void);
5308 extern cvar_t cl_locs_show;
5309 static void R_DrawLocs(void);
5310 static void R_DrawEntityBBoxes(void);
5311 static void R_DrawModelDecals(void);
5312 extern cvar_t cl_decals_newsystem;
5313 extern qboolean r_shadow_usingdeferredprepass;
5314 void R_RenderScene(void)
5316 r_refdef.stats.renders++;
5320 // don't let sound skip if going slow
5321 if (r_refdef.scene.extraupdate)
5324 R_MeshQueue_BeginScene();
5328 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);
5330 if (cl.csqc_vidvars.drawworld)
5332 // don't let sound skip if going slow
5333 if (r_refdef.scene.extraupdate)
5336 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5338 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5339 if (r_timereport_active)
5340 R_TimeReport("worldsky");
5343 if (R_DrawBrushModelsSky() && r_timereport_active)
5344 R_TimeReport("bmodelsky");
5346 if (skyrendermasked && skyrenderlater)
5348 // we have to force off the water clipping plane while rendering sky
5352 if (r_timereport_active)
5353 R_TimeReport("sky");
5357 R_AnimCache_CacheVisibleEntities();
5358 if (r_timereport_active)
5359 R_TimeReport("animation");
5361 R_Shadow_PrepareLights();
5362 if (r_timereport_active)
5363 R_TimeReport("preparelights");
5365 if (r_shadow_usingdeferredprepass)
5366 R_Shadow_DrawPrepass();
5368 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5370 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5371 if (r_timereport_active)
5372 R_TimeReport("worlddepth");
5374 if (r_depthfirst.integer >= 2)
5376 R_DrawModelsDepth();
5377 if (r_timereport_active)
5378 R_TimeReport("modeldepth");
5381 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5383 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5384 if (r_timereport_active)
5385 R_TimeReport("world");
5388 // don't let sound skip if going slow
5389 if (r_refdef.scene.extraupdate)
5393 if (r_timereport_active)
5394 R_TimeReport("models");
5396 // don't let sound skip if going slow
5397 if (r_refdef.scene.extraupdate)
5400 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5402 R_DrawModelShadows();
5403 R_ResetViewRendering3D();
5404 // don't let sound skip if going slow
5405 if (r_refdef.scene.extraupdate)
5409 if (!r_shadow_usingdeferredprepass)
5411 R_Shadow_DrawLights();
5412 if (r_timereport_active)
5413 R_TimeReport("rtlights");
5416 // don't let sound skip if going slow
5417 if (r_refdef.scene.extraupdate)
5420 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5422 R_DrawModelShadows();
5423 R_ResetViewRendering3D();
5424 // don't let sound skip if going slow
5425 if (r_refdef.scene.extraupdate)
5429 if (cl.csqc_vidvars.drawworld)
5431 if (cl_decals_newsystem.integer)
5433 R_DrawModelDecals();
5434 if (r_timereport_active)
5435 R_TimeReport("modeldecals");
5440 if (r_timereport_active)
5441 R_TimeReport("decals");
5445 if (r_timereport_active)
5446 R_TimeReport("particles");
5449 if (r_timereport_active)
5450 R_TimeReport("explosions");
5452 R_DrawLightningBeams();
5453 if (r_timereport_active)
5454 R_TimeReport("lightning");
5457 R_SetupGenericShader(true);
5458 VM_CL_AddPolygonsToMeshQueue();
5460 if (r_refdef.view.showdebug)
5462 if (cl_locs_show.integer)
5465 if (r_timereport_active)
5466 R_TimeReport("showlocs");
5469 if (r_drawportals.integer)
5472 if (r_timereport_active)
5473 R_TimeReport("portals");
5476 if (r_showbboxes.value > 0)
5478 R_DrawEntityBBoxes();
5479 if (r_timereport_active)
5480 R_TimeReport("bboxes");
5484 R_SetupGenericShader(true);
5485 R_MeshQueue_RenderTransparent();
5486 if (r_timereport_active)
5487 R_TimeReport("drawtrans");
5489 R_SetupGenericShader(true);
5491 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))
5493 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5494 if (r_timereport_active)
5495 R_TimeReport("worlddebug");
5496 R_DrawModelsDebug();
5497 if (r_timereport_active)
5498 R_TimeReport("modeldebug");
5501 R_SetupGenericShader(true);
5503 if (cl.csqc_vidvars.drawworld)
5505 R_Shadow_DrawCoronas();
5506 if (r_timereport_active)
5507 R_TimeReport("coronas");
5510 // don't let sound skip if going slow
5511 if (r_refdef.scene.extraupdate)
5514 R_ResetViewRendering2D();
5517 static const unsigned short bboxelements[36] =
5527 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5530 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5532 RSurf_ActiveWorldEntity();
5534 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5535 GL_DepthMask(false);
5536 GL_DepthRange(0, 1);
5537 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5538 R_Mesh_ResetTextureState();
5540 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5541 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5542 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5543 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5544 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5545 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5546 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5547 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5548 R_FillColors(color4f, 8, cr, cg, cb, ca);
5549 if (r_refdef.fogenabled)
5551 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5553 f1 = RSurf_FogVertex(v);
5555 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5556 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5557 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5560 R_Mesh_VertexPointer(vertex3f, 0, 0);
5561 R_Mesh_ColorPointer(color4f, 0, 0);
5562 R_Mesh_ResetTextureState();
5563 R_SetupGenericShader(false);
5564 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5567 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5571 prvm_edict_t *edict;
5572 prvm_prog_t *prog_save = prog;
5574 // this function draws bounding boxes of server entities
5578 GL_CullFace(GL_NONE);
5579 R_SetupGenericShader(false);
5583 for (i = 0;i < numsurfaces;i++)
5585 edict = PRVM_EDICT_NUM(surfacelist[i]);
5586 switch ((int)edict->fields.server->solid)
5588 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5589 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5590 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5591 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5592 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5593 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5595 color[3] *= r_showbboxes.value;
5596 color[3] = bound(0, color[3], 1);
5597 GL_DepthTest(!r_showdisabledepthtest.integer);
5598 GL_CullFace(r_refdef.view.cullface_front);
5599 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5605 static void R_DrawEntityBBoxes(void)
5608 prvm_edict_t *edict;
5610 prvm_prog_t *prog_save = prog;
5612 // this function draws bounding boxes of server entities
5618 for (i = 0;i < prog->num_edicts;i++)
5620 edict = PRVM_EDICT_NUM(i);
5621 if (edict->priv.server->free)
5623 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5624 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5626 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5628 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5629 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5635 static const int nomodelelement3i[24] =
5647 static const unsigned short nomodelelement3s[24] =
5659 static const float nomodelvertex3f[6*3] =
5669 static const float nomodelcolor4f[6*4] =
5671 0.0f, 0.0f, 0.5f, 1.0f,
5672 0.0f, 0.0f, 0.5f, 1.0f,
5673 0.0f, 0.5f, 0.0f, 1.0f,
5674 0.0f, 0.5f, 0.0f, 1.0f,
5675 0.5f, 0.0f, 0.0f, 1.0f,
5676 0.5f, 0.0f, 0.0f, 1.0f
5679 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5685 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);
5687 // this is only called once per entity so numsurfaces is always 1, and
5688 // surfacelist is always {0}, so this code does not handle batches
5690 if (rsurface.ent_flags & RENDER_ADDITIVE)
5692 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5693 GL_DepthMask(false);
5695 else if (rsurface.colormod[3] < 1)
5697 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5698 GL_DepthMask(false);
5702 GL_BlendFunc(GL_ONE, GL_ZERO);
5705 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5706 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5707 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5708 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5709 R_SetupGenericShader(false);
5710 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5711 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5712 R_Mesh_ColorPointer(color4f, 0, 0);
5713 for (i = 0, c = color4f;i < 6;i++, c += 4)
5715 c[0] *= rsurface.colormod[0];
5716 c[1] *= rsurface.colormod[1];
5717 c[2] *= rsurface.colormod[2];
5718 c[3] *= rsurface.colormod[3];
5720 if (r_refdef.fogenabled)
5722 for (i = 0, c = color4f;i < 6;i++, c += 4)
5724 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5726 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5727 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5728 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5731 R_Mesh_ResetTextureState();
5732 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5735 void R_DrawNoModel(entity_render_t *ent)
5738 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5739 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5740 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5742 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5745 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5747 vec3_t right1, right2, diff, normal;
5749 VectorSubtract (org2, org1, normal);
5751 // calculate 'right' vector for start
5752 VectorSubtract (r_refdef.view.origin, org1, diff);
5753 CrossProduct (normal, diff, right1);
5754 VectorNormalize (right1);
5756 // calculate 'right' vector for end
5757 VectorSubtract (r_refdef.view.origin, org2, diff);
5758 CrossProduct (normal, diff, right2);
5759 VectorNormalize (right2);
5761 vert[ 0] = org1[0] + width * right1[0];
5762 vert[ 1] = org1[1] + width * right1[1];
5763 vert[ 2] = org1[2] + width * right1[2];
5764 vert[ 3] = org1[0] - width * right1[0];
5765 vert[ 4] = org1[1] - width * right1[1];
5766 vert[ 5] = org1[2] - width * right1[2];
5767 vert[ 6] = org2[0] - width * right2[0];
5768 vert[ 7] = org2[1] - width * right2[1];
5769 vert[ 8] = org2[2] - width * right2[2];
5770 vert[ 9] = org2[0] + width * right2[0];
5771 vert[10] = org2[1] + width * right2[1];
5772 vert[11] = org2[2] + width * right2[2];
5775 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)
5777 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5778 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5779 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5780 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5781 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5782 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5783 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5784 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5785 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5786 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5787 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5788 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5791 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5796 VectorSet(v, x, y, z);
5797 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5798 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5800 if (i == mesh->numvertices)
5802 if (mesh->numvertices < mesh->maxvertices)
5804 VectorCopy(v, vertex3f);
5805 mesh->numvertices++;
5807 return mesh->numvertices;
5813 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5817 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5818 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5819 e = mesh->element3i + mesh->numtriangles * 3;
5820 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5822 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5823 if (mesh->numtriangles < mesh->maxtriangles)
5828 mesh->numtriangles++;
5830 element[1] = element[2];
5834 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5838 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5839 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5840 e = mesh->element3i + mesh->numtriangles * 3;
5841 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5843 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5844 if (mesh->numtriangles < mesh->maxtriangles)
5849 mesh->numtriangles++;
5851 element[1] = element[2];
5855 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5856 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5858 int planenum, planenum2;
5861 mplane_t *plane, *plane2;
5863 double temppoints[2][256*3];
5864 // figure out how large a bounding box we need to properly compute this brush
5866 for (w = 0;w < numplanes;w++)
5867 maxdist = max(maxdist, fabs(planes[w].dist));
5868 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5869 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5870 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5874 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5875 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5877 if (planenum2 == planenum)
5879 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);
5882 if (tempnumpoints < 3)
5884 // generate elements forming a triangle fan for this polygon
5885 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5889 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)
5891 texturelayer_t *layer;
5892 layer = t->currentlayers + t->currentnumlayers++;
5894 layer->depthmask = depthmask;
5895 layer->blendfunc1 = blendfunc1;
5896 layer->blendfunc2 = blendfunc2;
5897 layer->texture = texture;
5898 layer->texmatrix = *matrix;
5899 layer->color[0] = r;
5900 layer->color[1] = g;
5901 layer->color[2] = b;
5902 layer->color[3] = a;
5905 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5908 index = parms[2] + r_refdef.scene.time * parms[3];
5909 index -= floor(index);
5913 case Q3WAVEFUNC_NONE:
5914 case Q3WAVEFUNC_NOISE:
5915 case Q3WAVEFUNC_COUNT:
5918 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5919 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5920 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5921 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5922 case Q3WAVEFUNC_TRIANGLE:
5924 f = index - floor(index);
5935 return (float)(parms[0] + parms[1] * f);
5938 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5943 matrix4x4_t matrix, temp;
5944 switch(tcmod->tcmod)
5948 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5949 matrix = r_waterscrollmatrix;
5951 matrix = identitymatrix;
5953 case Q3TCMOD_ENTITYTRANSLATE:
5954 // this is used in Q3 to allow the gamecode to control texcoord
5955 // scrolling on the entity, which is not supported in darkplaces yet.
5956 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5958 case Q3TCMOD_ROTATE:
5959 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5960 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5961 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5964 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5966 case Q3TCMOD_SCROLL:
5967 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5969 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5970 w = (int) tcmod->parms[0];
5971 h = (int) tcmod->parms[1];
5972 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5974 idx = (int) floor(f * w * h);
5975 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5977 case Q3TCMOD_STRETCH:
5978 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5979 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5981 case Q3TCMOD_TRANSFORM:
5982 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5983 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5984 VectorSet(tcmat + 6, 0 , 0 , 1);
5985 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5986 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5988 case Q3TCMOD_TURBULENT:
5989 // this is handled in the RSurf_PrepareVertices function
5990 matrix = identitymatrix;
5994 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5997 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5999 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
6000 char name[MAX_QPATH];
6001 skinframe_t *skinframe;
6002 unsigned char pixels[296*194];
6003 strlcpy(cache->name, skinname, sizeof(cache->name));
6004 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6005 if (developer_loading.integer)
6006 Con_Printf("loading %s\n", name);
6007 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6008 if (!skinframe || !skinframe->base)
6011 fs_offset_t filesize;
6013 f = FS_LoadFile(name, tempmempool, true, &filesize);
6016 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
6017 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6021 cache->skinframe = skinframe;
6024 texture_t *R_GetCurrentTexture(texture_t *t)
6027 const entity_render_t *ent = rsurface.entity;
6028 dp_model_t *model = ent->model;
6029 q3shaderinfo_layer_tcmod_t *tcmod;
6031 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
6032 return t->currentframe;
6033 t->update_lastrenderframe = r_frame;
6034 t->update_lastrenderentity = (void *)ent;
6036 // switch to an alternate material if this is a q1bsp animated material
6038 texture_t *texture = t;
6039 int s = rsurface.ent_skinnum;
6040 if ((unsigned int)s >= (unsigned int)model->numskins)
6042 if (model->skinscenes)
6044 if (model->skinscenes[s].framecount > 1)
6045 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6047 s = model->skinscenes[s].firstframe;
6050 t = t + s * model->num_surfaces;
6053 // use an alternate animation if the entity's frame is not 0,
6054 // and only if the texture has an alternate animation
6055 if (rsurface.ent_alttextures && t->anim_total[1])
6056 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6058 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6060 texture->currentframe = t;
6063 // update currentskinframe to be a qw skin or animation frame
6064 if (rsurface.ent_qwskin >= 0)
6066 i = rsurface.ent_qwskin;
6067 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6069 r_qwskincache_size = cl.maxclients;
6071 Mem_Free(r_qwskincache);
6072 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6074 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6075 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6076 t->currentskinframe = r_qwskincache[i].skinframe;
6077 if (t->currentskinframe == NULL)
6078 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6080 else if (t->numskinframes >= 2)
6081 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6082 if (t->backgroundnumskinframes >= 2)
6083 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6085 t->currentmaterialflags = t->basematerialflags;
6086 t->currentalpha = rsurface.colormod[3];
6087 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6088 t->currentalpha *= r_wateralpha.value;
6089 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6090 t->currentalpha *= t->r_water_wateralpha;
6091 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6092 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6093 if (!(rsurface.ent_flags & RENDER_LIGHT))
6094 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6095 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6097 // pick a model lighting mode
6098 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6099 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6101 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6103 if (rsurface.ent_flags & RENDER_ADDITIVE)
6104 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6105 else if (t->currentalpha < 1)
6106 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6107 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6108 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6109 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6110 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6111 if (t->backgroundnumskinframes)
6112 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6113 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6115 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6116 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6119 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6120 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6121 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6123 // there is no tcmod
6124 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6126 t->currenttexmatrix = r_waterscrollmatrix;
6127 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6129 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6131 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6132 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6135 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6136 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6137 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6138 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6140 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6141 if (t->currentskinframe->qpixels)
6142 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6143 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6144 t->glosstexture = r_texture_black;
6145 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6146 t->backgroundglosstexture = r_texture_black;
6147 t->specularpower = r_shadow_glossexponent.value;
6148 // TODO: store reference values for these in the texture?
6149 t->specularscale = 0;
6150 if (r_shadow_gloss.integer > 0)
6152 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6154 if (r_shadow_glossintensity.value > 0)
6156 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6157 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6158 t->specularscale = r_shadow_glossintensity.value;
6161 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6163 t->glosstexture = r_texture_white;
6164 t->backgroundglosstexture = r_texture_white;
6165 t->specularscale = r_shadow_gloss2intensity.value;
6166 t->specularpower = r_shadow_gloss2exponent.value;
6169 t->specularscale *= t->specularscalemod;
6170 t->specularpower *= t->specularpowermod;
6172 // lightmaps mode looks bad with dlights using actual texturing, so turn
6173 // off the colormap and glossmap, but leave the normalmap on as it still
6174 // accurately represents the shading involved
6175 if (gl_lightmaps.integer)
6177 t->basetexture = r_texture_grey128;
6178 t->backgroundbasetexture = NULL;
6179 t->specularscale = 0;
6180 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6183 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
6184 VectorClear(t->dlightcolor);
6185 t->currentnumlayers = 0;
6186 if (t->currentmaterialflags & MATERIALFLAG_WALL)
6188 int blendfunc1, blendfunc2;
6190 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6192 blendfunc1 = GL_SRC_ALPHA;
6193 blendfunc2 = GL_ONE;
6195 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6197 blendfunc1 = GL_SRC_ALPHA;
6198 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6200 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6202 blendfunc1 = t->customblendfunc[0];
6203 blendfunc2 = t->customblendfunc[1];
6207 blendfunc1 = GL_ONE;
6208 blendfunc2 = GL_ZERO;
6210 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
6211 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6213 // fullbright is not affected by r_refdef.lightmapintensity
6214 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]);
6215 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6216 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]);
6217 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6218 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]);
6222 vec3_t ambientcolor;
6224 // set the color tint used for lights affecting this surface
6225 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
6227 // q3bsp has no lightmap updates, so the lightstylevalue that
6228 // would normally be baked into the lightmap must be
6229 // applied to the color
6230 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
6231 if (model->type == mod_brushq3)
6232 colorscale *= r_refdef.scene.rtlightstylevalue[0];
6233 colorscale *= r_refdef.lightmapintensity;
6234 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
6235 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
6236 // basic lit geometry
6237 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]);
6238 // add pants/shirt if needed
6239 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6240 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]);
6241 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6242 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]);
6243 // now add ambient passes if needed
6244 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
6246 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]);
6247 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6248 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]);
6249 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6250 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]);
6253 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
6254 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]);
6255 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
6257 // if this is opaque use alpha blend which will darken the earlier
6260 // if this is an alpha blended material, all the earlier passes
6261 // were darkened by fog already, so we only need to add the fog
6262 // color ontop through the fog mask texture
6264 // if this is an additive blended material, all the earlier passes
6265 // were darkened by fog already, and we should not add fog color
6266 // (because the background was not darkened, there is no fog color
6267 // that was lost behind it).
6268 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.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
6272 return t->currentframe;
6275 rsurfacestate_t rsurface;
6277 void R_Mesh_ResizeArrays(int newvertices)
6280 if (rsurface.array_size >= newvertices)
6282 if (rsurface.array_modelvertex3f)
6283 Mem_Free(rsurface.array_modelvertex3f);
6284 rsurface.array_size = (newvertices + 1023) & ~1023;
6285 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6286 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
6287 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
6288 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
6289 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
6290 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
6291 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6292 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6293 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
6294 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
6295 rsurface.array_color4f = base + rsurface.array_size * 27;
6296 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6299 void RSurf_ActiveWorldEntity(void)
6301 dp_model_t *model = r_refdef.scene.worldmodel;
6302 //if (rsurface.entity == r_refdef.scene.worldentity)
6304 rsurface.entity = r_refdef.scene.worldentity;
6305 rsurface.skeleton = NULL;
6306 rsurface.ent_skinnum = 0;
6307 rsurface.ent_qwskin = -1;
6308 rsurface.ent_shadertime = 0;
6309 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6310 if (rsurface.array_size < model->surfmesh.num_vertices)
6311 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6312 rsurface.matrix = identitymatrix;
6313 rsurface.inversematrix = identitymatrix;
6314 rsurface.matrixscale = 1;
6315 rsurface.inversematrixscale = 1;
6316 R_Mesh_Matrix(&identitymatrix);
6317 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6318 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6319 rsurface.fograngerecip = r_refdef.fograngerecip;
6320 rsurface.fogheightfade = r_refdef.fogheightfade;
6321 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6322 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6323 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6324 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6325 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6326 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6327 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6328 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
6329 rsurface.colormod[3] = 1;
6330 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);
6331 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6332 rsurface.frameblend[0].lerp = 1;
6333 rsurface.ent_alttextures = false;
6334 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6335 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6336 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6337 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6338 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6339 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6340 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6341 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6342 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6343 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6344 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6345 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6346 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6347 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6348 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6349 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6350 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6351 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6352 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6353 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6354 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6355 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6356 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6357 rsurface.modelelement3i = model->surfmesh.data_element3i;
6358 rsurface.modelelement3s = model->surfmesh.data_element3s;
6359 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6360 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6361 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6362 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6363 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6364 rsurface.modelsurfaces = model->data_surfaces;
6365 rsurface.generatedvertex = false;
6366 rsurface.vertex3f = rsurface.modelvertex3f;
6367 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6368 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6369 rsurface.svector3f = rsurface.modelsvector3f;
6370 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6371 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6372 rsurface.tvector3f = rsurface.modeltvector3f;
6373 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6374 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6375 rsurface.normal3f = rsurface.modelnormal3f;
6376 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6377 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6378 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6381 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
6383 dp_model_t *model = ent->model;
6384 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6386 rsurface.entity = (entity_render_t *)ent;
6387 rsurface.skeleton = ent->skeleton;
6388 rsurface.ent_skinnum = ent->skinnum;
6389 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;
6390 rsurface.ent_shadertime = ent->shadertime;
6391 rsurface.ent_flags = ent->flags;
6392 if (rsurface.array_size < model->surfmesh.num_vertices)
6393 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6394 rsurface.matrix = ent->matrix;
6395 rsurface.inversematrix = ent->inversematrix;
6396 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6397 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6398 R_Mesh_Matrix(&rsurface.matrix);
6399 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6400 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6401 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6402 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6403 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6404 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6405 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6406 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6407 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6408 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6409 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6410 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
6411 rsurface.colormod[3] = ent->alpha;
6412 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
6413 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6414 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6415 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6416 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6417 if (ent->model->brush.submodel && !prepass)
6419 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6420 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6422 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6424 if (ent->animcache_vertex3f && !r_framedata_failed)
6426 rsurface.modelvertex3f = ent->animcache_vertex3f;
6427 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
6428 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
6429 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
6431 else if (wanttangents)
6433 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6434 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6435 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6436 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6437 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6439 else if (wantnormals)
6441 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6442 rsurface.modelsvector3f = NULL;
6443 rsurface.modeltvector3f = NULL;
6444 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6445 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6449 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6450 rsurface.modelsvector3f = NULL;
6451 rsurface.modeltvector3f = NULL;
6452 rsurface.modelnormal3f = NULL;
6453 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6455 rsurface.modelvertex3f_bufferobject = 0;
6456 rsurface.modelvertex3f_bufferoffset = 0;
6457 rsurface.modelsvector3f_bufferobject = 0;
6458 rsurface.modelsvector3f_bufferoffset = 0;
6459 rsurface.modeltvector3f_bufferobject = 0;
6460 rsurface.modeltvector3f_bufferoffset = 0;
6461 rsurface.modelnormal3f_bufferobject = 0;
6462 rsurface.modelnormal3f_bufferoffset = 0;
6463 rsurface.generatedvertex = true;
6467 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6468 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6469 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6470 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6471 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6472 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6473 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6474 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6475 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6476 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6477 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6478 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6479 rsurface.generatedvertex = false;
6481 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6482 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6483 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6484 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6485 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6486 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6487 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6488 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6489 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6490 rsurface.modelelement3i = model->surfmesh.data_element3i;
6491 rsurface.modelelement3s = model->surfmesh.data_element3s;
6492 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6493 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6494 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6495 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6496 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6497 rsurface.modelsurfaces = model->data_surfaces;
6498 rsurface.vertex3f = rsurface.modelvertex3f;
6499 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6500 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6501 rsurface.svector3f = rsurface.modelsvector3f;
6502 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6503 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6504 rsurface.tvector3f = rsurface.modeltvector3f;
6505 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6506 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6507 rsurface.normal3f = rsurface.modelnormal3f;
6508 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6509 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6510 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6513 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)
6515 rsurface.entity = r_refdef.scene.worldentity;
6516 rsurface.skeleton = NULL;
6517 rsurface.ent_skinnum = 0;
6518 rsurface.ent_qwskin = -1;
6519 rsurface.ent_shadertime = shadertime;
6520 rsurface.ent_flags = entflags;
6521 rsurface.modelnum_vertices = numvertices;
6522 rsurface.modelnum_triangles = numtriangles;
6523 if (rsurface.array_size < rsurface.modelnum_vertices)
6524 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6525 rsurface.matrix = *matrix;
6526 rsurface.inversematrix = *inversematrix;
6527 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6528 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6529 R_Mesh_Matrix(&rsurface.matrix);
6530 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6531 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6532 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6533 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6534 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6535 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6536 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6537 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6538 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6539 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6540 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6541 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
6542 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);
6543 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6544 rsurface.frameblend[0].lerp = 1;
6545 rsurface.ent_alttextures = false;
6546 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6547 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6550 rsurface.modelvertex3f = vertex3f;
6551 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6552 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6553 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6555 else if (wantnormals)
6557 rsurface.modelvertex3f = vertex3f;
6558 rsurface.modelsvector3f = NULL;
6559 rsurface.modeltvector3f = NULL;
6560 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6564 rsurface.modelvertex3f = vertex3f;
6565 rsurface.modelsvector3f = NULL;
6566 rsurface.modeltvector3f = NULL;
6567 rsurface.modelnormal3f = NULL;
6569 rsurface.modelvertex3f_bufferobject = 0;
6570 rsurface.modelvertex3f_bufferoffset = 0;
6571 rsurface.modelsvector3f_bufferobject = 0;
6572 rsurface.modelsvector3f_bufferoffset = 0;
6573 rsurface.modeltvector3f_bufferobject = 0;
6574 rsurface.modeltvector3f_bufferoffset = 0;
6575 rsurface.modelnormal3f_bufferobject = 0;
6576 rsurface.modelnormal3f_bufferoffset = 0;
6577 rsurface.generatedvertex = true;
6578 rsurface.modellightmapcolor4f = color4f;
6579 rsurface.modellightmapcolor4f_bufferobject = 0;
6580 rsurface.modellightmapcolor4f_bufferoffset = 0;
6581 rsurface.modeltexcoordtexture2f = texcoord2f;
6582 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6583 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6584 rsurface.modeltexcoordlightmap2f = NULL;
6585 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6586 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6587 rsurface.modelelement3i = element3i;
6588 rsurface.modelelement3s = element3s;
6589 rsurface.modelelement3i_bufferobject = 0;
6590 rsurface.modelelement3s_bufferobject = 0;
6591 rsurface.modellightmapoffsets = NULL;
6592 rsurface.modelsurfaces = NULL;
6593 rsurface.vertex3f = rsurface.modelvertex3f;
6594 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6595 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6596 rsurface.svector3f = rsurface.modelsvector3f;
6597 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6598 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6599 rsurface.tvector3f = rsurface.modeltvector3f;
6600 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6601 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6602 rsurface.normal3f = rsurface.modelnormal3f;
6603 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6604 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6605 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6607 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6609 if ((wantnormals || wanttangents) && !normal3f)
6610 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6611 if (wanttangents && !svector3f)
6612 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);
6616 float RSurf_FogPoint(const float *v)
6618 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6619 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6620 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6621 float FogHeightFade = r_refdef.fogheightfade;
6623 unsigned int fogmasktableindex;
6624 if (r_refdef.fogplaneviewabove)
6625 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6627 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6628 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6629 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6632 float RSurf_FogVertex(const float *v)
6634 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6635 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6636 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6637 float FogHeightFade = rsurface.fogheightfade;
6639 unsigned int fogmasktableindex;
6640 if (r_refdef.fogplaneviewabove)
6641 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6643 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6644 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6645 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6648 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6649 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6652 int texturesurfaceindex;
6657 const float *v1, *in_tc;
6659 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6661 q3shaderinfo_deform_t *deform;
6662 // 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
6663 if (rsurface.generatedvertex)
6665 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6666 generatenormals = true;
6667 for (i = 0;i < Q3MAXDEFORMS;i++)
6669 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6671 generatetangents = true;
6672 generatenormals = true;
6674 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6675 generatenormals = true;
6677 if (generatenormals && !rsurface.modelnormal3f)
6679 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6680 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6681 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6682 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6684 if (generatetangents && !rsurface.modelsvector3f)
6686 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6687 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6688 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6689 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6690 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6691 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6692 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);
6695 rsurface.vertex3f = rsurface.modelvertex3f;
6696 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6697 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6698 rsurface.svector3f = rsurface.modelsvector3f;
6699 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6700 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6701 rsurface.tvector3f = rsurface.modeltvector3f;
6702 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6703 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6704 rsurface.normal3f = rsurface.modelnormal3f;
6705 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6706 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6707 // if vertices are deformed (sprite flares and things in maps, possibly
6708 // water waves, bulges and other deformations), generate them into
6709 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6710 // (may be static model data or generated data for an animated model, or
6711 // the previous deform pass)
6712 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6714 switch (deform->deform)
6717 case Q3DEFORM_PROJECTIONSHADOW:
6718 case Q3DEFORM_TEXT0:
6719 case Q3DEFORM_TEXT1:
6720 case Q3DEFORM_TEXT2:
6721 case Q3DEFORM_TEXT3:
6722 case Q3DEFORM_TEXT4:
6723 case Q3DEFORM_TEXT5:
6724 case Q3DEFORM_TEXT6:
6725 case Q3DEFORM_TEXT7:
6728 case Q3DEFORM_AUTOSPRITE:
6729 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6730 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6731 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6732 VectorNormalize(newforward);
6733 VectorNormalize(newright);
6734 VectorNormalize(newup);
6735 // make deformed versions of only the model vertices used by the specified surfaces
6736 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6738 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6739 // a single autosprite surface can contain multiple sprites...
6740 for (j = 0;j < surface->num_vertices - 3;j += 4)
6742 VectorClear(center);
6743 for (i = 0;i < 4;i++)
6744 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6745 VectorScale(center, 0.25f, center);
6746 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6747 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6748 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6749 for (i = 0;i < 4;i++)
6751 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6752 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6755 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);
6756 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);
6758 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6759 rsurface.vertex3f_bufferobject = 0;
6760 rsurface.vertex3f_bufferoffset = 0;
6761 rsurface.svector3f = rsurface.array_deformedsvector3f;
6762 rsurface.svector3f_bufferobject = 0;
6763 rsurface.svector3f_bufferoffset = 0;
6764 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6765 rsurface.tvector3f_bufferobject = 0;
6766 rsurface.tvector3f_bufferoffset = 0;
6767 rsurface.normal3f = rsurface.array_deformednormal3f;
6768 rsurface.normal3f_bufferobject = 0;
6769 rsurface.normal3f_bufferoffset = 0;
6771 case Q3DEFORM_AUTOSPRITE2:
6772 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6773 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6774 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6775 VectorNormalize(newforward);
6776 VectorNormalize(newright);
6777 VectorNormalize(newup);
6778 // make deformed versions of only the model vertices used by the specified surfaces
6779 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6781 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6782 const float *v1, *v2;
6792 memset(shortest, 0, sizeof(shortest));
6793 // a single autosprite surface can contain multiple sprites...
6794 for (j = 0;j < surface->num_vertices - 3;j += 4)
6796 VectorClear(center);
6797 for (i = 0;i < 4;i++)
6798 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6799 VectorScale(center, 0.25f, center);
6800 // find the two shortest edges, then use them to define the
6801 // axis vectors for rotating around the central axis
6802 for (i = 0;i < 6;i++)
6804 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6805 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6807 Debug_PolygonBegin(NULL, 0);
6808 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6809 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);
6810 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6813 l = VectorDistance2(v1, v2);
6814 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6816 l += (1.0f / 1024.0f);
6817 if (shortest[0].length2 > l || i == 0)
6819 shortest[1] = shortest[0];
6820 shortest[0].length2 = l;
6821 shortest[0].v1 = v1;
6822 shortest[0].v2 = v2;
6824 else if (shortest[1].length2 > l || i == 1)
6826 shortest[1].length2 = l;
6827 shortest[1].v1 = v1;
6828 shortest[1].v2 = v2;
6831 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6832 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6834 Debug_PolygonBegin(NULL, 0);
6835 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6836 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);
6837 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6840 // this calculates the right vector from the shortest edge
6841 // and the up vector from the edge midpoints
6842 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6843 VectorNormalize(right);
6844 VectorSubtract(end, start, up);
6845 VectorNormalize(up);
6846 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6847 VectorSubtract(rsurface.localvieworigin, center, forward);
6848 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6849 VectorNegate(forward, forward);
6850 VectorReflect(forward, 0, up, forward);
6851 VectorNormalize(forward);
6852 CrossProduct(up, forward, newright);
6853 VectorNormalize(newright);
6855 Debug_PolygonBegin(NULL, 0);
6856 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);
6857 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6858 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6862 Debug_PolygonBegin(NULL, 0);
6863 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6864 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6865 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6868 // rotate the quad around the up axis vector, this is made
6869 // especially easy by the fact we know the quad is flat,
6870 // so we only have to subtract the center position and
6871 // measure distance along the right vector, and then
6872 // multiply that by the newright vector and add back the
6874 // we also need to subtract the old position to undo the
6875 // displacement from the center, which we do with a
6876 // DotProduct, the subtraction/addition of center is also
6877 // optimized into DotProducts here
6878 l = DotProduct(right, center);
6879 for (i = 0;i < 4;i++)
6881 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6882 f = DotProduct(right, v1) - l;
6883 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6886 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);
6887 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);
6889 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6890 rsurface.vertex3f_bufferobject = 0;
6891 rsurface.vertex3f_bufferoffset = 0;
6892 rsurface.svector3f = rsurface.array_deformedsvector3f;
6893 rsurface.svector3f_bufferobject = 0;
6894 rsurface.svector3f_bufferoffset = 0;
6895 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6896 rsurface.tvector3f_bufferobject = 0;
6897 rsurface.tvector3f_bufferoffset = 0;
6898 rsurface.normal3f = rsurface.array_deformednormal3f;
6899 rsurface.normal3f_bufferobject = 0;
6900 rsurface.normal3f_bufferoffset = 0;
6902 case Q3DEFORM_NORMAL:
6903 // deform the normals to make reflections wavey
6904 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6906 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6907 for (j = 0;j < surface->num_vertices;j++)
6910 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6911 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6912 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6913 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6914 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6915 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6916 VectorNormalize(normal);
6918 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);
6920 rsurface.svector3f = rsurface.array_deformedsvector3f;
6921 rsurface.svector3f_bufferobject = 0;
6922 rsurface.svector3f_bufferoffset = 0;
6923 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6924 rsurface.tvector3f_bufferobject = 0;
6925 rsurface.tvector3f_bufferoffset = 0;
6926 rsurface.normal3f = rsurface.array_deformednormal3f;
6927 rsurface.normal3f_bufferobject = 0;
6928 rsurface.normal3f_bufferoffset = 0;
6931 // deform vertex array to make wavey water and flags and such
6932 waveparms[0] = deform->waveparms[0];
6933 waveparms[1] = deform->waveparms[1];
6934 waveparms[2] = deform->waveparms[2];
6935 waveparms[3] = deform->waveparms[3];
6936 // this is how a divisor of vertex influence on deformation
6937 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6938 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6939 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6941 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6942 for (j = 0;j < surface->num_vertices;j++)
6944 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6945 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6946 // if the wavefunc depends on time, evaluate it per-vertex
6949 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6950 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6952 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6955 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6956 rsurface.vertex3f_bufferobject = 0;
6957 rsurface.vertex3f_bufferoffset = 0;
6959 case Q3DEFORM_BULGE:
6960 // deform vertex array to make the surface have moving bulges
6961 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6963 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6964 for (j = 0;j < surface->num_vertices;j++)
6966 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6967 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6970 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6971 rsurface.vertex3f_bufferobject = 0;
6972 rsurface.vertex3f_bufferoffset = 0;
6975 // deform vertex array
6976 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6977 VectorScale(deform->parms, scale, waveparms);
6978 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6980 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6981 for (j = 0;j < surface->num_vertices;j++)
6982 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6984 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6985 rsurface.vertex3f_bufferobject = 0;
6986 rsurface.vertex3f_bufferoffset = 0;
6990 // generate texcoords based on the chosen texcoord source
6991 switch(rsurface.texture->tcgen.tcgen)
6994 case Q3TCGEN_TEXTURE:
6995 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6996 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6997 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6999 case Q3TCGEN_LIGHTMAP:
7000 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
7001 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7002 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7004 case Q3TCGEN_VECTOR:
7005 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7007 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7008 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)
7010 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
7011 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
7014 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7015 rsurface.texcoordtexture2f_bufferobject = 0;
7016 rsurface.texcoordtexture2f_bufferoffset = 0;
7018 case Q3TCGEN_ENVIRONMENT:
7019 // make environment reflections using a spheremap
7020 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7022 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7023 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
7024 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
7025 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
7026 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
7028 // identical to Q3A's method, but executed in worldspace so
7029 // carried models can be shiny too
7031 float viewer[3], d, reflected[3], worldreflected[3];
7033 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
7034 // VectorNormalize(viewer);
7036 d = DotProduct(normal, viewer);
7038 reflected[0] = normal[0]*2*d - viewer[0];
7039 reflected[1] = normal[1]*2*d - viewer[1];
7040 reflected[2] = normal[2]*2*d - viewer[2];
7041 // note: this is proportinal to viewer, so we can normalize later
7043 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7044 VectorNormalize(worldreflected);
7046 // note: this sphere map only uses world x and z!
7047 // so positive and negative y will LOOK THE SAME.
7048 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7049 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7052 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7053 rsurface.texcoordtexture2f_bufferobject = 0;
7054 rsurface.texcoordtexture2f_bufferoffset = 0;
7057 // the only tcmod that needs software vertex processing is turbulent, so
7058 // check for it here and apply the changes if needed
7059 // and we only support that as the first one
7060 // (handling a mixture of turbulent and other tcmods would be problematic
7061 // without punting it entirely to a software path)
7062 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7064 amplitude = rsurface.texture->tcmods[0].parms[1];
7065 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7066 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7068 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7069 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)
7071 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7072 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7075 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7076 rsurface.texcoordtexture2f_bufferobject = 0;
7077 rsurface.texcoordtexture2f_bufferoffset = 0;
7079 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7080 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7081 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7082 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7085 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7088 const msurface_t *surface = texturesurfacelist[0];
7089 const msurface_t *surface2;
7094 // TODO: lock all array ranges before render, rather than on each surface
7095 if (texturenumsurfaces == 1)
7097 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
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);
7100 else if (r_batchmode.integer == 2)
7102 #define MAXBATCHTRIANGLES 4096
7103 int batchtriangles = 0;
7104 static int batchelements[MAXBATCHTRIANGLES*3];
7105 for (i = 0;i < texturenumsurfaces;i = j)
7107 surface = texturesurfacelist[i];
7109 if (surface->num_triangles > MAXBATCHTRIANGLES)
7111 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);
7114 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7115 batchtriangles = surface->num_triangles;
7116 firstvertex = surface->num_firstvertex;
7117 endvertex = surface->num_firstvertex + surface->num_vertices;
7118 for (;j < texturenumsurfaces;j++)
7120 surface2 = texturesurfacelist[j];
7121 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7123 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7124 batchtriangles += surface2->num_triangles;
7125 firstvertex = min(firstvertex, surface2->num_firstvertex);
7126 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7128 surface2 = texturesurfacelist[j-1];
7129 numvertices = endvertex - firstvertex;
7130 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7133 else if (r_batchmode.integer == 1)
7135 for (i = 0;i < texturenumsurfaces;i = j)
7137 surface = texturesurfacelist[i];
7138 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7139 if (texturesurfacelist[j] != surface2)
7141 surface2 = texturesurfacelist[j-1];
7142 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7143 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7144 GL_LockArrays(surface->num_firstvertex, numvertices);
7145 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7150 for (i = 0;i < texturenumsurfaces;i++)
7152 surface = texturesurfacelist[i];
7153 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7154 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);
7159 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
7161 int i, planeindex, vertexindex;
7165 r_waterstate_waterplane_t *p, *bestp;
7166 const msurface_t *surface;
7167 if (r_waterstate.renderingscene)
7169 for (i = 0;i < texturenumsurfaces;i++)
7171 surface = texturesurfacelist[i];
7172 if (lightmaptexunit >= 0)
7173 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7174 if (deluxemaptexunit >= 0)
7175 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7176 // pick the closest matching water plane
7179 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7182 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7184 Matrix4x4_Transform(&rsurface.matrix, v, vert);
7185 d += fabs(PlaneDiff(vert, &p->plane));
7187 if (bestd > d || !bestp)
7195 if (refractiontexunit >= 0)
7196 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
7197 if (reflectiontexunit >= 0)
7198 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
7202 if (refractiontexunit >= 0)
7203 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
7204 if (reflectiontexunit >= 0)
7205 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
7207 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7208 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7212 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
7216 const msurface_t *surface = texturesurfacelist[0];
7217 const msurface_t *surface2;
7222 // TODO: lock all array ranges before render, rather than on each surface
7223 if (texturenumsurfaces == 1)
7225 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7226 if (deluxemaptexunit >= 0)
7227 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7228 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7229 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);
7231 else if (r_batchmode.integer == 2)
7233 #define MAXBATCHTRIANGLES 4096
7234 int batchtriangles = 0;
7235 int batchelements[MAXBATCHTRIANGLES*3];
7236 for (i = 0;i < texturenumsurfaces;i = j)
7238 surface = texturesurfacelist[i];
7239 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7240 if (deluxemaptexunit >= 0)
7241 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7243 if (surface->num_triangles > MAXBATCHTRIANGLES)
7245 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);
7248 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7249 batchtriangles = surface->num_triangles;
7250 firstvertex = surface->num_firstvertex;
7251 endvertex = surface->num_firstvertex + surface->num_vertices;
7252 for (;j < texturenumsurfaces;j++)
7254 surface2 = texturesurfacelist[j];
7255 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7257 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7258 batchtriangles += surface2->num_triangles;
7259 firstvertex = min(firstvertex, surface2->num_firstvertex);
7260 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7262 surface2 = texturesurfacelist[j-1];
7263 numvertices = endvertex - firstvertex;
7264 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7267 else if (r_batchmode.integer == 1)
7270 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
7271 for (i = 0;i < texturenumsurfaces;i = j)
7273 surface = texturesurfacelist[i];
7274 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7275 if (texturesurfacelist[j] != surface2)
7277 Con_Printf(" %i", j - i);
7280 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
7282 for (i = 0;i < texturenumsurfaces;i = j)
7284 surface = texturesurfacelist[i];
7285 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7286 if (deluxemaptexunit >= 0)
7287 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7288 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7289 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7292 Con_Printf(" %i", j - i);
7294 surface2 = texturesurfacelist[j-1];
7295 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7296 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7297 GL_LockArrays(surface->num_firstvertex, numvertices);
7298 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7306 for (i = 0;i < texturenumsurfaces;i++)
7308 surface = texturesurfacelist[i];
7309 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7310 if (deluxemaptexunit >= 0)
7311 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7312 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7313 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);
7318 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7321 int texturesurfaceindex;
7322 if (r_showsurfaces.integer == 2)
7324 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7326 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7327 for (j = 0;j < surface->num_triangles;j++)
7329 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7330 GL_Color(f, f, f, 1);
7331 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7337 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7339 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7340 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7341 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);
7342 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7343 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);
7348 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7350 int texturesurfaceindex;
7354 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7356 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7357 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
7365 rsurface.lightmapcolor4f = rsurface.array_color4f;
7366 rsurface.lightmapcolor4f_bufferobject = 0;
7367 rsurface.lightmapcolor4f_bufferoffset = 0;
7370 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7372 int texturesurfaceindex;
7378 if (rsurface.lightmapcolor4f)
7380 // generate color arrays for the surfaces in this list
7381 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7383 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7384 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)
7386 f = RSurf_FogVertex(v);
7396 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7398 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7399 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)
7401 f = RSurf_FogVertex(v);
7409 rsurface.lightmapcolor4f = rsurface.array_color4f;
7410 rsurface.lightmapcolor4f_bufferobject = 0;
7411 rsurface.lightmapcolor4f_bufferoffset = 0;
7414 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7416 int texturesurfaceindex;
7422 if (!rsurface.lightmapcolor4f)
7424 // generate color arrays for the surfaces in this list
7425 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7427 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7428 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)
7430 f = RSurf_FogVertex(v);
7431 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7432 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7433 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7437 rsurface.lightmapcolor4f = rsurface.array_color4f;
7438 rsurface.lightmapcolor4f_bufferobject = 0;
7439 rsurface.lightmapcolor4f_bufferoffset = 0;
7442 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7444 int texturesurfaceindex;
7448 if (!rsurface.lightmapcolor4f)
7450 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7452 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7453 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)
7461 rsurface.lightmapcolor4f = rsurface.array_color4f;
7462 rsurface.lightmapcolor4f_bufferobject = 0;
7463 rsurface.lightmapcolor4f_bufferoffset = 0;
7466 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7468 int texturesurfaceindex;
7472 if (!rsurface.lightmapcolor4f)
7474 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7476 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7477 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)
7479 c2[0] = c[0] + r_refdef.scene.ambient;
7480 c2[1] = c[1] + r_refdef.scene.ambient;
7481 c2[2] = c[2] + r_refdef.scene.ambient;
7485 rsurface.lightmapcolor4f = rsurface.array_color4f;
7486 rsurface.lightmapcolor4f_bufferobject = 0;
7487 rsurface.lightmapcolor4f_bufferoffset = 0;
7490 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7493 rsurface.lightmapcolor4f = NULL;
7494 rsurface.lightmapcolor4f_bufferobject = 0;
7495 rsurface.lightmapcolor4f_bufferoffset = 0;
7496 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7497 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7498 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7499 GL_Color(r, g, b, a);
7500 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7503 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7505 // TODO: optimize applyfog && applycolor case
7506 // just apply fog if necessary, and tint the fog color array if necessary
7507 rsurface.lightmapcolor4f = NULL;
7508 rsurface.lightmapcolor4f_bufferobject = 0;
7509 rsurface.lightmapcolor4f_bufferoffset = 0;
7510 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7511 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7512 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7513 GL_Color(r, g, b, a);
7514 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7517 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7519 int texturesurfaceindex;
7523 if (texturesurfacelist[0]->lightmapinfo)
7525 // generate color arrays for the surfaces in this list
7526 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7528 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7529 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7531 if (surface->lightmapinfo->samples)
7533 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7534 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7535 VectorScale(lm, scale, c);
7536 if (surface->lightmapinfo->styles[1] != 255)
7538 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7540 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7541 VectorMA(c, scale, lm, c);
7542 if (surface->lightmapinfo->styles[2] != 255)
7545 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7546 VectorMA(c, scale, lm, c);
7547 if (surface->lightmapinfo->styles[3] != 255)
7550 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7551 VectorMA(c, scale, lm, c);
7561 rsurface.lightmapcolor4f = rsurface.array_color4f;
7562 rsurface.lightmapcolor4f_bufferobject = 0;
7563 rsurface.lightmapcolor4f_bufferoffset = 0;
7567 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7568 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7569 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7571 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7572 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7573 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7574 GL_Color(r, g, b, a);
7575 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7578 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7580 int texturesurfaceindex;
7587 vec3_t ambientcolor;
7588 vec3_t diffusecolor;
7592 VectorCopy(rsurface.modellight_lightdir, lightdir);
7593 f = 0.5f * r_refdef.lightmapintensity;
7594 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7595 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7596 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7597 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7598 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7599 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7601 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7603 // generate color arrays for the surfaces in this list
7604 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7606 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7607 int numverts = surface->num_vertices;
7608 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7609 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7610 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7611 // q3-style directional shading
7612 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7614 if ((f = DotProduct(n, lightdir)) > 0)
7615 VectorMA(ambientcolor, f, diffusecolor, c);
7617 VectorCopy(ambientcolor, c);
7625 rsurface.lightmapcolor4f = rsurface.array_color4f;
7626 rsurface.lightmapcolor4f_bufferobject = 0;
7627 rsurface.lightmapcolor4f_bufferoffset = 0;
7628 *applycolor = false;
7632 *r = ambientcolor[0];
7633 *g = ambientcolor[1];
7634 *b = ambientcolor[2];
7635 rsurface.lightmapcolor4f = NULL;
7636 rsurface.lightmapcolor4f_bufferobject = 0;
7637 rsurface.lightmapcolor4f_bufferoffset = 0;
7641 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7643 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7644 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7645 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7646 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7647 GL_Color(r, g, b, a);
7648 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7651 void RSurf_SetupDepthAndCulling(void)
7653 // submodels are biased to avoid z-fighting with world surfaces that they
7654 // may be exactly overlapping (avoids z-fighting artifacts on certain
7655 // doors and things in Quake maps)
7656 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7657 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7658 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7659 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7662 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7664 // transparent sky would be ridiculous
7665 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7667 R_SetupGenericShader(false);
7668 skyrenderlater = true;
7669 RSurf_SetupDepthAndCulling();
7671 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7672 // skymasking on them, and Quake3 never did sky masking (unlike
7673 // software Quake and software Quake2), so disable the sky masking
7674 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7675 // and skymasking also looks very bad when noclipping outside the
7676 // level, so don't use it then either.
7677 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7679 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7680 R_Mesh_ColorPointer(NULL, 0, 0);
7681 R_Mesh_ResetTextureState();
7682 if (skyrendermasked)
7684 R_SetupDepthOrShadowShader();
7685 // depth-only (masking)
7686 GL_ColorMask(0,0,0,0);
7687 // just to make sure that braindead drivers don't draw
7688 // anything despite that colormask...
7689 GL_BlendFunc(GL_ZERO, GL_ONE);
7693 R_SetupGenericShader(false);
7695 GL_BlendFunc(GL_ONE, GL_ZERO);
7697 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7698 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7699 if (skyrendermasked)
7700 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7702 R_Mesh_ResetTextureState();
7703 GL_Color(1, 1, 1, 1);
7706 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
7707 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
7708 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
7710 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7713 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7714 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7715 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7716 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7717 if (rsurface.texture->backgroundcurrentskinframe)
7719 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7720 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7721 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7722 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7724 if (rsurface.texture->colormapping)
7726 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7727 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7729 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7730 if (r_shadow_usingdeferredprepass)
7732 R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture));
7733 R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture));
7735 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7736 R_Mesh_ColorPointer(NULL, 0, 0);
7738 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7740 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass)
7742 // render background
7743 GL_BlendFunc(GL_ONE, GL_ZERO);
7745 GL_AlphaTest(false);
7747 GL_Color(1, 1, 1, 1);
7748 R_Mesh_ColorPointer(NULL, 0, 0);
7750 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7751 if (r_glsl_permutation)
7753 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7754 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7755 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7756 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7757 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7758 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7759 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);
7761 GL_LockArrays(0, 0);
7763 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7764 GL_DepthMask(false);
7765 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7766 R_Mesh_ColorPointer(NULL, 0, 0);
7768 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7769 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7770 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7773 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
7774 if (!r_glsl_permutation)
7777 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7778 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7779 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7780 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7781 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7783 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7785 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7787 GL_BlendFunc(GL_ONE, GL_ZERO);
7789 GL_AlphaTest(false);
7793 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7794 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7795 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
7798 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7800 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7801 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);
7803 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7807 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7808 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);
7810 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7812 GL_LockArrays(0, 0);
7815 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7817 // OpenGL 1.3 path - anything not completely ancient
7818 int texturesurfaceindex;
7819 qboolean applycolor;
7822 const texturelayer_t *layer;
7823 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7825 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7828 int layertexrgbscale;
7829 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7831 if (layerindex == 0)
7835 GL_AlphaTest(false);
7836 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7839 GL_DepthMask(layer->depthmask && writedepth);
7840 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7841 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7843 layertexrgbscale = 4;
7844 VectorScale(layer->color, 0.25f, layercolor);
7846 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7848 layertexrgbscale = 2;
7849 VectorScale(layer->color, 0.5f, layercolor);
7853 layertexrgbscale = 1;
7854 VectorScale(layer->color, 1.0f, layercolor);
7856 layercolor[3] = layer->color[3];
7857 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7858 R_Mesh_ColorPointer(NULL, 0, 0);
7859 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
7860 switch (layer->type)
7862 case TEXTURELAYERTYPE_LITTEXTURE:
7863 // single-pass lightmapped texture with 2x rgbscale
7864 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
7865 R_Mesh_TexMatrix(0, NULL);
7866 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7867 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7868 R_Mesh_TexBind(1, R_GetTexture(layer->texture));
7869 R_Mesh_TexMatrix(1, &layer->texmatrix);
7870 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7871 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7872 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7873 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7874 else if (rsurface.uselightmaptexture)
7875 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7877 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7879 case TEXTURELAYERTYPE_TEXTURE:
7880 // singletexture unlit texture with transparency support
7881 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7882 R_Mesh_TexMatrix(0, &layer->texmatrix);
7883 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7884 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7885 R_Mesh_TexBind(1, 0);
7886 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
7887 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7889 case TEXTURELAYERTYPE_FOG:
7890 // singletexture fogging
7893 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7894 R_Mesh_TexMatrix(0, &layer->texmatrix);
7895 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7896 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7900 R_Mesh_TexBind(0, 0);
7901 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
7903 R_Mesh_TexBind(1, 0);
7904 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
7905 // generate a color array for the fog pass
7906 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7907 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7913 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7914 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)
7916 f = 1 - RSurf_FogVertex(v);
7917 c[0] = layercolor[0];
7918 c[1] = layercolor[1];
7919 c[2] = layercolor[2];
7920 c[3] = f * layercolor[3];
7923 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7926 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7928 GL_LockArrays(0, 0);
7931 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7933 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7934 GL_AlphaTest(false);
7938 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7940 // OpenGL 1.1 - crusty old voodoo path
7941 int texturesurfaceindex;
7944 const texturelayer_t *layer;
7945 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7947 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7949 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7951 if (layerindex == 0)
7955 GL_AlphaTest(false);
7956 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7959 GL_DepthMask(layer->depthmask && writedepth);
7960 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7961 R_Mesh_ColorPointer(NULL, 0, 0);
7962 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
7963 switch (layer->type)
7965 case TEXTURELAYERTYPE_LITTEXTURE:
7966 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7968 // two-pass lit texture with 2x rgbscale
7969 // first the lightmap pass
7970 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
7971 R_Mesh_TexMatrix(0, NULL);
7972 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7973 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7974 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7975 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7976 else if (rsurface.uselightmaptexture)
7977 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7979 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7980 GL_LockArrays(0, 0);
7981 // then apply the texture to it
7982 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7983 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7984 R_Mesh_TexMatrix(0, &layer->texmatrix);
7985 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7986 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7987 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);
7991 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7992 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7993 R_Mesh_TexMatrix(0, &layer->texmatrix);
7994 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7995 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7996 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7997 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);
7999 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);
8002 case TEXTURELAYERTYPE_TEXTURE:
8003 // singletexture unlit texture with transparency support
8004 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8005 R_Mesh_TexMatrix(0, &layer->texmatrix);
8006 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8007 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8008 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);
8010 case TEXTURELAYERTYPE_FOG:
8011 // singletexture fogging
8014 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8015 R_Mesh_TexMatrix(0, &layer->texmatrix);
8016 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8017 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8021 R_Mesh_TexBind(0, 0);
8022 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8024 // generate a color array for the fog pass
8025 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8026 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8032 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8033 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)
8035 f = 1 - RSurf_FogVertex(v);
8036 c[0] = layer->color[0];
8037 c[1] = layer->color[1];
8038 c[2] = layer->color[2];
8039 c[3] = f * layer->color[3];
8042 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8045 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8047 GL_LockArrays(0, 0);
8050 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8052 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8053 GL_AlphaTest(false);
8057 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8061 GL_AlphaTest(false);
8062 R_Mesh_ColorPointer(NULL, 0, 0);
8063 R_Mesh_ResetTextureState();
8064 R_SetupGenericShader(false);
8066 if(rsurface.texture && rsurface.texture->currentskinframe)
8068 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8069 c[3] *= rsurface.texture->currentalpha;
8079 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
8081 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8082 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8083 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8086 // brighten it up (as texture value 127 means "unlit")
8087 c[0] *= 2 * r_refdef.view.colorscale;
8088 c[1] *= 2 * r_refdef.view.colorscale;
8089 c[2] *= 2 * r_refdef.view.colorscale;
8091 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8092 c[3] *= r_wateralpha.value;
8094 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8096 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8097 GL_DepthMask(false);
8099 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8101 GL_BlendFunc(GL_ONE, GL_ONE);
8102 GL_DepthMask(false);
8104 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8106 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8107 GL_DepthMask(false);
8109 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8111 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8112 GL_DepthMask(false);
8116 GL_BlendFunc(GL_ONE, GL_ZERO);
8117 GL_DepthMask(writedepth);
8120 rsurface.lightmapcolor4f = NULL;
8122 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8124 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8126 rsurface.lightmapcolor4f = NULL;
8127 rsurface.lightmapcolor4f_bufferobject = 0;
8128 rsurface.lightmapcolor4f_bufferoffset = 0;
8130 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8132 qboolean applycolor = true;
8135 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8137 r_refdef.lightmapintensity = 1;
8138 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8139 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8143 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8145 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8146 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8147 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8150 if(!rsurface.lightmapcolor4f)
8151 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8153 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8154 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8155 if(r_refdef.fogenabled)
8156 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8158 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8159 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8162 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8165 RSurf_SetupDepthAndCulling();
8166 if (r_showsurfaces.integer == 3 && !prepass)
8168 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8171 switch (vid.renderpath)
8173 case RENDERPATH_GL20:
8174 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8176 case RENDERPATH_GL13:
8177 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8179 case RENDERPATH_GL11:
8180 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8186 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8189 RSurf_SetupDepthAndCulling();
8190 if (r_showsurfaces.integer == 3 && !prepass)
8192 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8195 switch (vid.renderpath)
8197 case RENDERPATH_GL20:
8198 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8200 case RENDERPATH_GL13:
8201 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8203 case RENDERPATH_GL11:
8204 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8210 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8213 int texturenumsurfaces, endsurface;
8215 const msurface_t *surface;
8216 const msurface_t *texturesurfacelist[256];
8218 // if the model is static it doesn't matter what value we give for
8219 // wantnormals and wanttangents, so this logic uses only rules applicable
8220 // to a model, knowing that they are meaningless otherwise
8221 if (ent == r_refdef.scene.worldentity)
8222 RSurf_ActiveWorldEntity();
8223 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8224 RSurf_ActiveModelEntity(ent, false, false, false);
8227 switch (vid.renderpath)
8229 case RENDERPATH_GL20:
8230 RSurf_ActiveModelEntity(ent, true, true, false);
8232 case RENDERPATH_GL13:
8233 case RENDERPATH_GL11:
8234 RSurf_ActiveModelEntity(ent, true, false, false);
8239 if (r_transparentdepthmasking.integer)
8241 qboolean setup = false;
8242 for (i = 0;i < numsurfaces;i = j)
8245 surface = rsurface.modelsurfaces + surfacelist[i];
8246 texture = surface->texture;
8247 rsurface.texture = R_GetCurrentTexture(texture);
8248 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8249 // scan ahead until we find a different texture
8250 endsurface = min(i + 1024, numsurfaces);
8251 texturenumsurfaces = 0;
8252 texturesurfacelist[texturenumsurfaces++] = surface;
8253 for (;j < endsurface;j++)
8255 surface = rsurface.modelsurfaces + surfacelist[j];
8256 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8258 texturesurfacelist[texturenumsurfaces++] = surface;
8260 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
8262 // render the range of surfaces as depth
8266 GL_ColorMask(0,0,0,0);
8269 GL_BlendFunc(GL_ONE, GL_ZERO);
8271 GL_AlphaTest(false);
8272 R_Mesh_ColorPointer(NULL, 0, 0);
8273 R_Mesh_ResetTextureState();
8274 R_SetupDepthOrShadowShader();
8276 RSurf_SetupDepthAndCulling();
8277 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8278 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8281 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8284 for (i = 0;i < numsurfaces;i = j)
8287 surface = rsurface.modelsurfaces + surfacelist[i];
8288 texture = surface->texture;
8289 rsurface.texture = R_GetCurrentTexture(texture);
8290 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8291 // scan ahead until we find a different texture
8292 endsurface = min(i + 1024, numsurfaces);
8293 texturenumsurfaces = 0;
8294 texturesurfacelist[texturenumsurfaces++] = surface;
8295 for (;j < endsurface;j++)
8297 surface = rsurface.modelsurfaces + surfacelist[j];
8298 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8300 texturesurfacelist[texturenumsurfaces++] = surface;
8302 // render the range of surfaces
8303 if (ent == r_refdef.scene.worldentity)
8304 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8306 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8308 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8309 GL_AlphaTest(false);
8312 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
8314 // transparent surfaces get pushed off into the transparent queue
8315 int surfacelistindex;
8316 const msurface_t *surface;
8317 vec3_t tempcenter, center;
8318 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8320 surface = texturesurfacelist[surfacelistindex];
8321 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8322 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8323 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8324 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8325 if (queueentity->transparent_offset) // transparent offset
8327 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8328 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8329 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8331 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8335 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
8337 const entity_render_t *queueentity = r_refdef.scene.worldentity;
8341 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8343 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8345 RSurf_SetupDepthAndCulling();
8346 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8347 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8351 if (!rsurface.texture->currentnumlayers)
8353 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8354 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8356 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8358 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
8360 RSurf_SetupDepthAndCulling();
8361 GL_AlphaTest(false);
8362 R_Mesh_ColorPointer(NULL, 0, 0);
8363 R_Mesh_ResetTextureState();
8364 R_SetupGenericShader(false);
8365 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8367 GL_BlendFunc(GL_ONE, GL_ZERO);
8368 GL_Color(0, 0, 0, 1);
8369 GL_DepthTest(writedepth);
8370 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8372 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
8374 RSurf_SetupDepthAndCulling();
8375 GL_AlphaTest(false);
8376 R_Mesh_ColorPointer(NULL, 0, 0);
8377 R_Mesh_ResetTextureState();
8378 R_SetupGenericShader(false);
8379 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8381 GL_BlendFunc(GL_ONE, GL_ZERO);
8383 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8385 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8386 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8387 else if (!rsurface.texture->currentnumlayers)
8389 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8391 // in the deferred case, transparent surfaces were queued during prepass
8392 if (!r_shadow_usingdeferredprepass)
8393 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8397 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8398 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8403 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8407 // break the surface list down into batches by texture and use of lightmapping
8408 for (i = 0;i < numsurfaces;i = j)
8411 // texture is the base texture pointer, rsurface.texture is the
8412 // current frame/skin the texture is directing us to use (for example
8413 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8414 // use skin 1 instead)
8415 texture = surfacelist[i]->texture;
8416 rsurface.texture = R_GetCurrentTexture(texture);
8417 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8418 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8420 // if this texture is not the kind we want, skip ahead to the next one
8421 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8425 // simply scan ahead until we find a different texture or lightmap state
8426 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8428 // render the range of surfaces
8429 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
8433 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
8438 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8440 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8442 RSurf_SetupDepthAndCulling();
8443 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8444 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8448 if (!rsurface.texture->currentnumlayers)
8450 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8451 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8453 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8455 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8457 RSurf_SetupDepthAndCulling();
8458 GL_AlphaTest(false);
8459 R_Mesh_ColorPointer(NULL, 0, 0);
8460 R_Mesh_ResetTextureState();
8461 R_SetupGenericShader(false);
8462 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8464 GL_BlendFunc(GL_ONE, GL_ZERO);
8465 GL_Color(0, 0, 0, 1);
8466 GL_DepthTest(writedepth);
8467 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8469 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8471 RSurf_SetupDepthAndCulling();
8472 GL_AlphaTest(false);
8473 R_Mesh_ColorPointer(NULL, 0, 0);
8474 R_Mesh_ResetTextureState();
8475 R_SetupGenericShader(false);
8476 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8478 GL_BlendFunc(GL_ONE, GL_ZERO);
8480 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8482 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8483 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8484 else if (!rsurface.texture->currentnumlayers)
8486 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8488 // in the deferred case, transparent surfaces were queued during prepass
8489 if (!r_shadow_usingdeferredprepass)
8490 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8494 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8495 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8500 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8504 // break the surface list down into batches by texture and use of lightmapping
8505 for (i = 0;i < numsurfaces;i = j)
8508 // texture is the base texture pointer, rsurface.texture is the
8509 // current frame/skin the texture is directing us to use (for example
8510 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8511 // use skin 1 instead)
8512 texture = surfacelist[i]->texture;
8513 rsurface.texture = R_GetCurrentTexture(texture);
8514 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8515 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8517 // if this texture is not the kind we want, skip ahead to the next one
8518 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8522 // simply scan ahead until we find a different texture or lightmap state
8523 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8525 // render the range of surfaces
8526 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
8530 float locboxvertex3f[6*4*3] =
8532 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8533 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8534 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8535 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8536 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8537 1,0,0, 0,0,0, 0,1,0, 1,1,0
8540 unsigned short locboxelements[6*2*3] =
8550 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8553 cl_locnode_t *loc = (cl_locnode_t *)ent;
8555 float vertex3f[6*4*3];
8557 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8558 GL_DepthMask(false);
8559 GL_DepthRange(0, 1);
8560 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8562 GL_CullFace(GL_NONE);
8563 R_Mesh_Matrix(&identitymatrix);
8565 R_Mesh_VertexPointer(vertex3f, 0, 0);
8566 R_Mesh_ColorPointer(NULL, 0, 0);
8567 R_Mesh_ResetTextureState();
8568 R_SetupGenericShader(false);
8571 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8572 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8573 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8574 surfacelist[0] < 0 ? 0.5f : 0.125f);
8576 if (VectorCompare(loc->mins, loc->maxs))
8578 VectorSet(size, 2, 2, 2);
8579 VectorMA(loc->mins, -0.5f, size, mins);
8583 VectorCopy(loc->mins, mins);
8584 VectorSubtract(loc->maxs, loc->mins, size);
8587 for (i = 0;i < 6*4*3;)
8588 for (j = 0;j < 3;j++, i++)
8589 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8591 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8594 void R_DrawLocs(void)
8597 cl_locnode_t *loc, *nearestloc;
8599 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8600 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8602 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8603 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8607 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8609 if (decalsystem->decals)
8610 Mem_Free(decalsystem->decals);
8611 memset(decalsystem, 0, sizeof(*decalsystem));
8614 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)
8621 // expand or initialize the system
8622 if (decalsystem->maxdecals <= decalsystem->numdecals)
8624 decalsystem_t old = *decalsystem;
8625 qboolean useshortelements;
8626 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8627 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8628 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)));
8629 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8630 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8631 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8632 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8633 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8634 if (decalsystem->numdecals)
8635 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8637 Mem_Free(old.decals);
8638 for (i = 0;i < decalsystem->maxdecals*3;i++)
8639 decalsystem->element3i[i] = i;
8640 if (useshortelements)
8641 for (i = 0;i < decalsystem->maxdecals*3;i++)
8642 decalsystem->element3s[i] = i;
8645 // grab a decal and search for another free slot for the next one
8646 maxdecals = decalsystem->maxdecals;
8647 decals = decalsystem->decals;
8648 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8649 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8651 decalsystem->freedecal = i;
8652 if (decalsystem->numdecals <= i)
8653 decalsystem->numdecals = i + 1;
8655 // initialize the decal
8657 decal->triangleindex = triangleindex;
8658 decal->surfaceindex = surfaceindex;
8659 decal->decalsequence = decalsequence;
8660 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8661 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8662 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8663 decal->color4ub[0][3] = 255;
8664 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8665 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8666 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8667 decal->color4ub[1][3] = 255;
8668 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8669 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8670 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8671 decal->color4ub[2][3] = 255;
8672 decal->vertex3f[0][0] = v0[0];
8673 decal->vertex3f[0][1] = v0[1];
8674 decal->vertex3f[0][2] = v0[2];
8675 decal->vertex3f[1][0] = v1[0];
8676 decal->vertex3f[1][1] = v1[1];
8677 decal->vertex3f[1][2] = v1[2];
8678 decal->vertex3f[2][0] = v2[0];
8679 decal->vertex3f[2][1] = v2[1];
8680 decal->vertex3f[2][2] = v2[2];
8681 decal->texcoord2f[0][0] = t0[0];
8682 decal->texcoord2f[0][1] = t0[1];
8683 decal->texcoord2f[1][0] = t1[0];
8684 decal->texcoord2f[1][1] = t1[1];
8685 decal->texcoord2f[2][0] = t2[0];
8686 decal->texcoord2f[2][1] = t2[1];
8689 extern cvar_t cl_decals_bias;
8690 extern cvar_t cl_decals_models;
8691 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8692 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)
8694 matrix4x4_t projection;
8695 decalsystem_t *decalsystem;
8698 const float *vertex3f;
8699 const msurface_t *surface;
8700 const msurface_t *surfaces;
8701 const int *surfacelist;
8702 const texture_t *texture;
8706 int surfacelistindex;
8709 int decalsurfaceindex;
8714 float localorigin[3];
8715 float localnormal[3];
8726 float points[2][9][3];
8730 decalsystem = &ent->decalsystem;
8732 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8734 R_DecalSystem_Reset(&ent->decalsystem);
8738 if (!model->brush.data_nodes && !cl_decals_models.integer)
8740 if (decalsystem->model)
8741 R_DecalSystem_Reset(decalsystem);
8745 if (decalsystem->model != model)
8746 R_DecalSystem_Reset(decalsystem);
8747 decalsystem->model = model;
8749 RSurf_ActiveModelEntity(ent, false, false, false);
8751 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8752 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8753 VectorNormalize(localnormal);
8754 localsize = worldsize*rsurface.inversematrixscale;
8755 ilocalsize = 1.0f / localsize;
8756 localmins[0] = localorigin[0] - localsize;
8757 localmins[1] = localorigin[1] - localsize;
8758 localmins[2] = localorigin[2] - localsize;
8759 localmaxs[0] = localorigin[0] + localsize;
8760 localmaxs[1] = localorigin[1] + localsize;
8761 localmaxs[2] = localorigin[2] + localsize;
8763 //VectorCopy(localnormal, planes[4]);
8764 //VectorVectors(planes[4], planes[2], planes[0]);
8765 AnglesFromVectors(angles, localnormal, NULL, false);
8766 AngleVectors(angles, planes[0], planes[2], planes[4]);
8767 VectorNegate(planes[0], planes[1]);
8768 VectorNegate(planes[2], planes[3]);
8769 VectorNegate(planes[4], planes[5]);
8770 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8771 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8772 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8773 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8774 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8775 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8780 matrix4x4_t forwardprojection;
8781 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8782 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8787 float projectionvector[4][3];
8788 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8789 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8790 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8791 projectionvector[0][0] = planes[0][0] * ilocalsize;
8792 projectionvector[0][1] = planes[1][0] * ilocalsize;
8793 projectionvector[0][2] = planes[2][0] * ilocalsize;
8794 projectionvector[1][0] = planes[0][1] * ilocalsize;
8795 projectionvector[1][1] = planes[1][1] * ilocalsize;
8796 projectionvector[1][2] = planes[2][1] * ilocalsize;
8797 projectionvector[2][0] = planes[0][2] * ilocalsize;
8798 projectionvector[2][1] = planes[1][2] * ilocalsize;
8799 projectionvector[2][2] = planes[2][2] * ilocalsize;
8800 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8801 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8802 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8803 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8807 dynamic = model->surfmesh.isanimated;
8808 vertex3f = rsurface.modelvertex3f;
8809 numsurfacelist = model->nummodelsurfaces;
8810 surfacelist = model->sortedmodelsurfaces;
8811 surfaces = model->data_surfaces;
8812 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8814 surfaceindex = surfacelist[surfacelistindex];
8815 surface = surfaces + surfaceindex;
8816 // skip transparent surfaces
8817 texture = surface->texture;
8818 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8820 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8822 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8824 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8825 numvertices = surface->num_vertices;
8826 numtriangles = surface->num_triangles;
8827 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8829 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8831 index = 3*e[cornerindex];
8832 VectorCopy(vertex3f + index, v[cornerindex]);
8835 //TriangleNormal(v[0], v[1], v[2], normal);
8836 //if (DotProduct(normal, localnormal) < 0.0f)
8838 // clip by each of the box planes formed from the projection matrix
8839 // if anything survives, we emit the decal
8840 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]);
8843 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]);
8846 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]);
8849 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]);
8852 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]);
8855 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]);
8858 // some part of the triangle survived, so we have to accept it...
8861 // dynamic always uses the original triangle
8863 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8865 index = 3*e[cornerindex];
8866 VectorCopy(vertex3f + index, v[cornerindex]);
8869 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8871 // convert vertex positions to texcoords
8872 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8873 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8874 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8875 // calculate distance fade from the projection origin
8876 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8877 f = bound(0.0f, f, 1.0f);
8878 c[cornerindex][0] = r * f;
8879 c[cornerindex][1] = g * f;
8880 c[cornerindex][2] = b * f;
8881 c[cornerindex][3] = 1.0f;
8882 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8885 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);
8887 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8888 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);
8893 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8894 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)
8896 int renderentityindex;
8899 entity_render_t *ent;
8901 if (!cl_decals_newsystem.integer)
8904 worldmins[0] = worldorigin[0] - worldsize;
8905 worldmins[1] = worldorigin[1] - worldsize;
8906 worldmins[2] = worldorigin[2] - worldsize;
8907 worldmaxs[0] = worldorigin[0] + worldsize;
8908 worldmaxs[1] = worldorigin[1] + worldsize;
8909 worldmaxs[2] = worldorigin[2] + worldsize;
8911 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8913 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8915 ent = r_refdef.scene.entities[renderentityindex];
8916 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8919 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8923 typedef struct r_decalsystem_splatqueue_s
8932 r_decalsystem_splatqueue_t;
8934 int r_decalsystem_numqueued = 0;
8935 #define MAX_DECALSYSTEM_QUEUE 1024
8936 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8938 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)
8940 r_decalsystem_splatqueue_t *queue;
8942 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8945 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8946 VectorCopy(worldorigin, queue->worldorigin);
8947 VectorCopy(worldnormal, queue->worldnormal);
8948 Vector4Set(queue->color, r, g, b, a);
8949 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8950 queue->worldsize = worldsize;
8951 queue->decalsequence = cl.decalsequence++;
8954 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8957 r_decalsystem_splatqueue_t *queue;
8959 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8960 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);
8961 r_decalsystem_numqueued = 0;
8964 extern cvar_t cl_decals_max;
8965 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8968 decalsystem_t *decalsystem = &ent->decalsystem;
8975 if (!decalsystem->numdecals)
8978 if (r_showsurfaces.integer)
8981 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8983 R_DecalSystem_Reset(decalsystem);
8987 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8988 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8990 if (decalsystem->lastupdatetime)
8991 frametime = (cl.time - decalsystem->lastupdatetime);
8994 decalsystem->lastupdatetime = cl.time;
8995 decal = decalsystem->decals;
8996 numdecals = decalsystem->numdecals;
8998 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9000 if (decal->color4ub[0][3])
9002 decal->lived += frametime;
9003 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
9005 memset(decal, 0, sizeof(*decal));
9006 if (decalsystem->freedecal > i)
9007 decalsystem->freedecal = i;
9011 decal = decalsystem->decals;
9012 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
9015 // collapse the array by shuffling the tail decals into the gaps
9018 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
9019 decalsystem->freedecal++;
9020 if (decalsystem->freedecal == numdecals)
9022 decal[decalsystem->freedecal] = decal[--numdecals];
9025 decalsystem->numdecals = numdecals;
9029 // if there are no decals left, reset decalsystem
9030 R_DecalSystem_Reset(decalsystem);
9034 extern skinframe_t *decalskinframe;
9035 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9038 decalsystem_t *decalsystem = &ent->decalsystem;
9048 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9051 numdecals = decalsystem->numdecals;
9055 if (r_showsurfaces.integer)
9058 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9060 R_DecalSystem_Reset(decalsystem);
9064 // if the model is static it doesn't matter what value we give for
9065 // wantnormals and wanttangents, so this logic uses only rules applicable
9066 // to a model, knowing that they are meaningless otherwise
9067 if (ent == r_refdef.scene.worldentity)
9068 RSurf_ActiveWorldEntity();
9070 RSurf_ActiveModelEntity(ent, false, false, false);
9072 decalsystem->lastupdatetime = cl.time;
9073 decal = decalsystem->decals;
9075 fadedelay = cl_decals_time.value;
9076 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9078 // update vertex positions for animated models
9079 v3f = decalsystem->vertex3f;
9080 c4f = decalsystem->color4f;
9081 t2f = decalsystem->texcoord2f;
9082 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9084 if (!decal->color4ub[0][3])
9087 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9090 // update color values for fading decals
9091 if (decal->lived >= cl_decals_time.value)
9093 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9094 alpha *= (1.0f/255.0f);
9097 alpha = 1.0f/255.0f;
9099 c4f[ 0] = decal->color4ub[0][0] * alpha;
9100 c4f[ 1] = decal->color4ub[0][1] * alpha;
9101 c4f[ 2] = decal->color4ub[0][2] * alpha;
9103 c4f[ 4] = decal->color4ub[1][0] * alpha;
9104 c4f[ 5] = decal->color4ub[1][1] * alpha;
9105 c4f[ 6] = decal->color4ub[1][2] * alpha;
9107 c4f[ 8] = decal->color4ub[2][0] * alpha;
9108 c4f[ 9] = decal->color4ub[2][1] * alpha;
9109 c4f[10] = decal->color4ub[2][2] * alpha;
9112 t2f[0] = decal->texcoord2f[0][0];
9113 t2f[1] = decal->texcoord2f[0][1];
9114 t2f[2] = decal->texcoord2f[1][0];
9115 t2f[3] = decal->texcoord2f[1][1];
9116 t2f[4] = decal->texcoord2f[2][0];
9117 t2f[5] = decal->texcoord2f[2][1];
9119 // update vertex positions for animated models
9120 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9122 e = rsurface.modelelement3i + 3*decal->triangleindex;
9123 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9124 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9125 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9129 VectorCopy(decal->vertex3f[0], v3f);
9130 VectorCopy(decal->vertex3f[1], v3f + 3);
9131 VectorCopy(decal->vertex3f[2], v3f + 6);
9142 r_refdef.stats.drawndecals += numtris;
9144 if (r_refdef.fogenabled)
9146 switch(vid.renderpath)
9148 case RENDERPATH_GL20:
9149 case RENDERPATH_GL13:
9150 case RENDERPATH_GL11:
9151 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
9153 alpha = RSurf_FogVertex(v3f);
9162 // now render the decals all at once
9163 // (this assumes they all use one particle font texture!)
9164 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);
9165 R_Mesh_ResetTextureState();
9166 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9167 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9168 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9169 R_SetupGenericShader(true);
9170 GL_DepthMask(false);
9171 GL_DepthRange(0, 1);
9172 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9174 GL_CullFace(GL_NONE);
9175 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9176 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
9177 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
9178 GL_LockArrays(0, numtris * 3);
9179 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9180 GL_LockArrays(0, 0);
9184 static void R_DrawModelDecals(void)
9188 // fade faster when there are too many decals
9189 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9190 for (i = 0;i < r_refdef.scene.numentities;i++)
9191 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9193 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9194 for (i = 0;i < r_refdef.scene.numentities;i++)
9195 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9196 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9198 R_DecalSystem_ApplySplatEntitiesQueue();
9200 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9201 for (i = 0;i < r_refdef.scene.numentities;i++)
9202 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9204 r_refdef.stats.totaldecals += numdecals;
9206 if (r_showsurfaces.integer)
9209 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9211 for (i = 0;i < r_refdef.scene.numentities;i++)
9213 if (!r_refdef.viewcache.entityvisible[i])
9215 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9216 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9220 void R_DrawDebugModel(void)
9222 entity_render_t *ent = rsurface.entity;
9223 int i, j, k, l, flagsmask;
9224 const int *elements;
9226 const msurface_t *surface;
9227 dp_model_t *model = ent->model;
9230 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9232 R_Mesh_ColorPointer(NULL, 0, 0);
9233 R_Mesh_ResetTextureState();
9234 R_SetupGenericShader(false);
9235 GL_DepthRange(0, 1);
9236 GL_DepthTest(!r_showdisabledepthtest.integer);
9237 GL_DepthMask(false);
9238 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9240 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
9242 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9243 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
9245 if (brush->colbrushf && brush->colbrushf->numtriangles)
9247 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
9248 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);
9249 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
9252 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
9254 if (surface->num_collisiontriangles)
9256 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
9257 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);
9258 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
9263 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9265 if (r_showtris.integer || r_shownormals.integer)
9267 if (r_showdisabledepthtest.integer)
9269 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9270 GL_DepthMask(false);
9274 GL_BlendFunc(GL_ONE, GL_ZERO);
9277 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9279 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9281 rsurface.texture = R_GetCurrentTexture(surface->texture);
9282 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9284 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
9285 if (r_showtris.value > 0)
9287 if (!rsurface.texture->currentlayers->depthmask)
9288 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9289 else if (ent == r_refdef.scene.worldentity)
9290 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9292 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9293 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
9294 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
9295 R_Mesh_ColorPointer(NULL, 0, 0);
9296 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
9297 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9298 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
9299 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);
9300 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9303 if (r_shownormals.value < 0)
9306 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9308 VectorCopy(rsurface.vertex3f + l * 3, v);
9309 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9310 qglVertex3f(v[0], v[1], v[2]);
9311 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
9312 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9313 qglVertex3f(v[0], v[1], v[2]);
9318 if (r_shownormals.value > 0)
9321 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9323 VectorCopy(rsurface.vertex3f + l * 3, v);
9324 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9325 qglVertex3f(v[0], v[1], v[2]);
9326 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
9327 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9328 qglVertex3f(v[0], v[1], v[2]);
9333 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9335 VectorCopy(rsurface.vertex3f + l * 3, v);
9336 GL_Color(0, r_refdef.view.colorscale, 0, 1);
9337 qglVertex3f(v[0], v[1], v[2]);
9338 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
9339 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9340 qglVertex3f(v[0], v[1], v[2]);
9345 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9347 VectorCopy(rsurface.vertex3f + l * 3, v);
9348 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9349 qglVertex3f(v[0], v[1], v[2]);
9350 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
9351 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9352 qglVertex3f(v[0], v[1], v[2]);
9359 rsurface.texture = NULL;
9363 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
9364 int r_maxsurfacelist = 0;
9365 const msurface_t **r_surfacelist = NULL;
9366 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9368 int i, j, endj, f, flagsmask;
9370 dp_model_t *model = r_refdef.scene.worldmodel;
9371 msurface_t *surfaces;
9372 unsigned char *update;
9373 int numsurfacelist = 0;
9377 if (r_maxsurfacelist < model->num_surfaces)
9379 r_maxsurfacelist = model->num_surfaces;
9381 Mem_Free((msurface_t**)r_surfacelist);
9382 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9385 RSurf_ActiveWorldEntity();
9387 surfaces = model->data_surfaces;
9388 update = model->brushq1.lightmapupdateflags;
9390 // update light styles on this submodel
9391 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9393 model_brush_lightstyleinfo_t *style;
9394 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9396 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9398 int *list = style->surfacelist;
9399 style->value = r_refdef.scene.lightstylevalue[style->style];
9400 for (j = 0;j < style->numsurfaces;j++)
9401 update[list[j]] = true;
9406 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9411 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9417 rsurface.uselightmaptexture = false;
9418 rsurface.texture = NULL;
9419 rsurface.rtlight = NULL;
9421 // add visible surfaces to draw list
9422 for (i = 0;i < model->nummodelsurfaces;i++)
9424 j = model->sortedmodelsurfaces[i];
9425 if (r_refdef.viewcache.world_surfacevisible[j])
9426 r_surfacelist[numsurfacelist++] = surfaces + j;
9428 // update lightmaps if needed
9432 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9434 if (r_refdef.viewcache.world_surfacevisible[j])
9439 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9445 int count = model->brushq3.num_mergedlightmaps;
9446 for (i = 0;i < count;i++)
9448 if (model->brushq3.data_deluxemaps[i])
9449 R_FlushTexture(model->brushq3.data_deluxemaps[i]);
9450 if (model->brushq3.data_lightmaps[i])
9451 R_FlushTexture(model->brushq3.data_lightmaps[i]);
9455 // don't do anything if there were no surfaces
9456 if (!numsurfacelist)
9458 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9461 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9462 GL_AlphaTest(false);
9464 // add to stats if desired
9465 if (r_speeds.integer && !skysurfaces && !depthonly)
9467 r_refdef.stats.world_surfaces += numsurfacelist;
9468 for (j = 0;j < numsurfacelist;j++)
9469 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9472 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9475 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9477 int i, j, endj, f, flagsmask;
9479 dp_model_t *model = ent->model;
9480 msurface_t *surfaces;
9481 unsigned char *update;
9482 int numsurfacelist = 0;
9486 if (r_maxsurfacelist < model->num_surfaces)
9488 r_maxsurfacelist = model->num_surfaces;
9490 Mem_Free((msurface_t **)r_surfacelist);
9491 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9494 // if the model is static it doesn't matter what value we give for
9495 // wantnormals and wanttangents, so this logic uses only rules applicable
9496 // to a model, knowing that they are meaningless otherwise
9497 if (ent == r_refdef.scene.worldentity)
9498 RSurf_ActiveWorldEntity();
9499 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9500 RSurf_ActiveModelEntity(ent, false, false, false);
9502 RSurf_ActiveModelEntity(ent, true, true, true);
9504 RSurf_ActiveModelEntity(ent, false, false, false);
9507 switch (vid.renderpath)
9509 case RENDERPATH_GL20:
9510 RSurf_ActiveModelEntity(ent, true, true, false);
9512 case RENDERPATH_GL13:
9513 case RENDERPATH_GL11:
9514 RSurf_ActiveModelEntity(ent, true, false, false);
9519 surfaces = model->data_surfaces;
9520 update = model->brushq1.lightmapupdateflags;
9522 // update light styles
9523 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9525 model_brush_lightstyleinfo_t *style;
9526 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9528 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9530 int *list = style->surfacelist;
9531 style->value = r_refdef.scene.lightstylevalue[style->style];
9532 for (j = 0;j < style->numsurfaces;j++)
9533 update[list[j]] = true;
9538 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9543 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9549 rsurface.uselightmaptexture = false;
9550 rsurface.texture = NULL;
9551 rsurface.rtlight = NULL;
9553 // add visible surfaces to draw list
9554 for (i = 0;i < model->nummodelsurfaces;i++)
9555 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9556 // don't do anything if there were no surfaces
9557 if (!numsurfacelist)
9559 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9562 // update lightmaps if needed
9566 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9571 R_BuildLightMap(ent, surfaces + j);
9576 int count = model->brushq3.num_mergedlightmaps;
9577 for (i = 0;i < count;i++)
9579 if (model->brushq3.data_deluxemaps[i])
9580 R_FlushTexture(model->brushq3.data_deluxemaps[i]);
9581 if (model->brushq3.data_lightmaps[i])
9582 R_FlushTexture(model->brushq3.data_lightmaps[i]);
9587 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9589 R_BuildLightMap(ent, surfaces + j);
9590 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9591 GL_AlphaTest(false);
9593 // add to stats if desired
9594 if (r_speeds.integer && !skysurfaces && !depthonly)
9596 r_refdef.stats.entities_surfaces += numsurfacelist;
9597 for (j = 0;j < numsurfacelist;j++)
9598 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9601 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9604 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
9606 static texture_t texture;
9607 static msurface_t surface;
9608 const msurface_t *surfacelist = &surface;
9610 // fake enough texture and surface state to render this geometry
9612 texture.update_lastrenderframe = -1; // regenerate this texture
9613 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9614 texture.currentskinframe = skinframe;
9615 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9616 texture.specularscalemod = 1;
9617 texture.specularpowermod = 1;
9619 surface.texture = &texture;
9620 surface.num_triangles = numtriangles;
9621 surface.num_firsttriangle = firsttriangle;
9622 surface.num_vertices = numvertices;
9623 surface.num_firstvertex = firstvertex;
9626 rsurface.texture = R_GetCurrentTexture(surface.texture);
9627 rsurface.uselightmaptexture = false;
9628 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
9631 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)
9633 static msurface_t surface;
9634 const msurface_t *surfacelist = &surface;
9636 // fake enough texture and surface state to render this geometry
9638 surface.texture = texture;
9639 surface.num_triangles = numtriangles;
9640 surface.num_firsttriangle = firsttriangle;
9641 surface.num_vertices = numvertices;
9642 surface.num_firstvertex = firstvertex;
9645 rsurface.texture = R_GetCurrentTexture(surface.texture);
9646 rsurface.uselightmaptexture = false;
9647 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);