2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
33 qboolean r_loadnormalmap;
42 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
43 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
44 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
45 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
46 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
47 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
48 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
49 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
51 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
52 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
53 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
54 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
55 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
57 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
58 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
59 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
60 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
61 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
62 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
63 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
64 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
65 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
66 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
67 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
68 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
69 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
70 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
71 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
72 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
73 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
74 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
75 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
76 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
77 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
78 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
79 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
80 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
81 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
82 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
83 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
84 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
85 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
86 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
87 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
88 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
89 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
90 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
91 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
92 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
93 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
94 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
95 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
96 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
97 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
98 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "1", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
100 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
101 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
102 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
103 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
104 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
105 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
106 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
107 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
109 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
110 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
111 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
113 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
114 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
115 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
116 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
117 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
118 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
119 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
120 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
121 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
123 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
124 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
125 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
126 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
127 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
129 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
130 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
131 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
132 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
134 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
135 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
136 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
137 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
138 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
139 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
140 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
142 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
143 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
144 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
145 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
147 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
149 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
151 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
153 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
154 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
155 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
156 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
157 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
158 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
159 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
161 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
163 extern cvar_t v_glslgamma;
165 extern qboolean v_flipped_state;
167 static struct r_bloomstate_s
172 int bloomwidth, bloomheight;
174 int screentexturewidth, screentextureheight;
175 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
177 int bloomtexturewidth, bloomtextureheight;
178 rtexture_t *texture_bloom;
180 // arrays for rendering the screen passes
181 float screentexcoord2f[8];
182 float bloomtexcoord2f[8];
183 float offsettexcoord2f[8];
185 r_viewport_t viewport;
189 r_waterstate_t r_waterstate;
191 /// shadow volume bsp struct with automatically growing nodes buffer
194 rtexture_t *r_texture_blanknormalmap;
195 rtexture_t *r_texture_white;
196 rtexture_t *r_texture_grey128;
197 rtexture_t *r_texture_black;
198 rtexture_t *r_texture_notexture;
199 rtexture_t *r_texture_whitecube;
200 rtexture_t *r_texture_normalizationcube;
201 rtexture_t *r_texture_fogattenuation;
202 rtexture_t *r_texture_gammaramps;
203 unsigned int r_texture_gammaramps_serial;
204 //rtexture_t *r_texture_fogintensity;
206 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
207 unsigned int r_numqueries;
208 unsigned int r_maxqueries;
210 typedef struct r_qwskincache_s
212 char name[MAX_QPATH];
213 skinframe_t *skinframe;
217 static r_qwskincache_t *r_qwskincache;
218 static int r_qwskincache_size;
220 /// vertex coordinates for a quad that covers the screen exactly
221 const float r_screenvertex3f[12] =
229 extern void R_DrawModelShadows(void);
231 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
234 for (i = 0;i < verts;i++)
245 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
248 for (i = 0;i < verts;i++)
258 // FIXME: move this to client?
261 if (gamemode == GAME_NEHAHRA)
263 Cvar_Set("gl_fogenable", "0");
264 Cvar_Set("gl_fogdensity", "0.2");
265 Cvar_Set("gl_fogred", "0.3");
266 Cvar_Set("gl_foggreen", "0.3");
267 Cvar_Set("gl_fogblue", "0.3");
269 r_refdef.fog_density = 0;
270 r_refdef.fog_red = 0;
271 r_refdef.fog_green = 0;
272 r_refdef.fog_blue = 0;
273 r_refdef.fog_alpha = 1;
274 r_refdef.fog_start = 0;
275 r_refdef.fog_end = 16384;
276 r_refdef.fog_height = 1<<30;
277 r_refdef.fog_fadedepth = 128;
280 static void R_BuildBlankTextures(void)
282 unsigned char data[4];
283 data[2] = 128; // normal X
284 data[1] = 128; // normal Y
285 data[0] = 255; // normal Z
286 data[3] = 128; // height
287 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
297 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
302 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
305 static void R_BuildNoTexture(void)
308 unsigned char pix[16][16][4];
309 // this makes a light grey/dark grey checkerboard texture
310 for (y = 0;y < 16;y++)
312 for (x = 0;x < 16;x++)
314 if ((y < 8) ^ (x < 8))
330 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
333 static void R_BuildWhiteCube(void)
335 unsigned char data[6*1*1*4];
336 memset(data, 255, sizeof(data));
337 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
340 static void R_BuildNormalizationCube(void)
344 vec_t s, t, intensity;
346 unsigned char data[6][NORMSIZE][NORMSIZE][4];
347 for (side = 0;side < 6;side++)
349 for (y = 0;y < NORMSIZE;y++)
351 for (x = 0;x < NORMSIZE;x++)
353 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
354 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
389 intensity = 127.0f / sqrt(DotProduct(v, v));
390 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
391 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
392 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
393 data[side][y][x][3] = 255;
397 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
400 static void R_BuildFogTexture(void)
404 unsigned char data1[FOGWIDTH][4];
405 //unsigned char data2[FOGWIDTH][4];
408 r_refdef.fogmasktable_start = r_refdef.fog_start;
409 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
410 r_refdef.fogmasktable_range = r_refdef.fogrange;
411 r_refdef.fogmasktable_density = r_refdef.fog_density;
413 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
414 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
416 d = (x * r - r_refdef.fogmasktable_start);
417 if(developer.integer >= 100)
418 Con_Printf("%f ", d);
420 if (r_fog_exp2.integer)
421 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
423 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
424 if(developer.integer >= 100)
425 Con_Printf(" : %f ", alpha);
426 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
427 if(developer.integer >= 100)
428 Con_Printf(" = %f\n", alpha);
429 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
432 for (x = 0;x < FOGWIDTH;x++)
434 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
439 //data2[x][0] = 255 - b;
440 //data2[x][1] = 255 - b;
441 //data2[x][2] = 255 - b;
444 if (r_texture_fogattenuation)
446 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
447 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
451 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
452 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
456 static const char *builtinshaderstring =
457 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
458 "// written by Forest 'LordHavoc' Hale\n"
460 "// enable various extensions depending on permutation:\n"
462 "#ifdef MODE_DEPTH_OR_SHADOW\n"
463 "#ifdef VERTEX_SHADER\n"
466 " gl_Position = ftransform();\n"
469 "#else // !MODE_DEPTH_ORSHADOW\n"
470 "#ifdef MODE_SHOWDEPTH\n"
471 "#ifdef VERTEX_SHADER\n"
474 " gl_Position = ftransform();\n"
475 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
479 "#ifdef FRAGMENT_SHADER\n"
482 " gl_FragColor = gl_Color;\n"
485 "#else // !MODE_SHOWDEPTH\n"
486 "#ifdef MODE_POSTPROCESS\n"
487 "varying vec2 TexCoord1;\n"
488 "varying vec2 TexCoord2;\n"
490 "#ifdef VERTEX_SHADER\n"
493 " gl_Position = ftransform();\n"
494 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
496 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
501 "#ifdef FRAGMENT_SHADER\n"
502 "uniform sampler2D Texture_First;\n"
504 "uniform sampler2D Texture_Second;\n"
506 "#ifdef USEGAMMARAMPS\n"
507 "uniform sampler2D Texture_GammaRamps;\n"
509 "#ifdef USESATURATION\n"
510 "uniform float Saturation;\n"
512 "#ifdef USEVIEWTINT\n"
513 "uniform vec4 ViewTintColor;\n"
515 "//uncomment these if you want to use them:\n"
516 "uniform vec4 UserVec1;\n"
517 "// uniform vec4 UserVec2;\n"
518 "// uniform vec4 UserVec3;\n"
519 "// uniform vec4 UserVec4;\n"
520 "// uniform float ClientTime;\n"
521 "uniform vec2 PixelSize;\n"
524 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
526 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
528 "#ifdef USEVIEWTINT\n"
529 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
532 "#ifdef USEPOSTPROCESSING\n"
533 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
534 "// 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"
535 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
536 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
537 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
538 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
539 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
540 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
543 "#ifdef USESATURATION\n"
544 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
545 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
546 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
547 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
550 "#ifdef USEGAMMARAMPS\n"
551 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
552 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
553 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
557 "#else // !MODE_POSTPROCESS\n"
558 "#ifdef MODE_GENERIC\n"
559 "#ifdef USEDIFFUSE\n"
560 "varying vec2 TexCoord1;\n"
562 "#ifdef USESPECULAR\n"
563 "varying vec2 TexCoord2;\n"
565 "#ifdef VERTEX_SHADER\n"
568 " gl_FrontColor = gl_Color;\n"
569 "#ifdef USEDIFFUSE\n"
570 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
572 "#ifdef USESPECULAR\n"
573 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
575 " gl_Position = ftransform();\n"
579 "#ifdef FRAGMENT_SHADER\n"
580 "#ifdef USEDIFFUSE\n"
581 "uniform sampler2D Texture_First;\n"
583 "#ifdef USESPECULAR\n"
584 "uniform sampler2D Texture_Second;\n"
589 " gl_FragColor = gl_Color;\n"
590 "#ifdef USEDIFFUSE\n"
591 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
594 "#ifdef USESPECULAR\n"
595 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
597 "#ifdef USECOLORMAPPING\n"
598 " gl_FragColor *= tex2;\n"
601 " gl_FragColor += tex2;\n"
603 "#ifdef USEVERTEXTEXTUREBLEND\n"
604 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
608 "#else // !MODE_GENERIC\n"
609 "#ifdef MODE_BLOOMBLUR\n"
610 "varying TexCoord;\n"
611 "#ifdef VERTEX_SHADER\n"
614 " gl_FrontColor = gl_Color;\n"
615 " TexCoord = gl_MultiTexCoord0.xy;\n"
616 " gl_Position = ftransform();\n"
620 "#ifdef FRAGMENT_SHADER\n"
621 "uniform sampler2D Texture_First;\n"
622 "uniform vec4 BloomBlur_Parameters;\n"
627 " vec2 tc = TexCoord;\n"
628 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
629 " tc += BloomBlur_Parameters.xy;\n"
630 " for (i = 1;i < SAMPLES;i++)\n"
632 " color += texture2D(Texture_First, tc).rgb;\n"
633 " tc += BloomBlur_Parameters.xy;\n"
635 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
638 "#else // !MODE_BLOOMBLUR\n"
639 "#ifdef MODE_REFRACTION\n"
640 "varying vec2 TexCoord;\n"
641 "varying vec4 ModelViewProjectionPosition;\n"
642 "uniform mat4 TexMatrix;\n"
643 "#ifdef VERTEX_SHADER\n"
647 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
648 " gl_Position = ftransform();\n"
649 " ModelViewProjectionPosition = gl_Position;\n"
653 "#ifdef FRAGMENT_SHADER\n"
654 "uniform sampler2D Texture_Normal;\n"
655 "uniform sampler2D Texture_Refraction;\n"
656 "uniform sampler2D Texture_Reflection;\n"
658 "uniform vec4 DistortScaleRefractReflect;\n"
659 "uniform vec4 ScreenScaleRefractReflect;\n"
660 "uniform vec4 ScreenCenterRefractReflect;\n"
661 "uniform vec4 RefractColor;\n"
662 "uniform vec4 ReflectColor;\n"
663 "uniform float ReflectFactor;\n"
664 "uniform float ReflectOffset;\n"
668 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
669 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
670 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
671 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
672 " // FIXME temporary hack to detect the case that the reflection\n"
673 " // gets blackened at edges due to leaving the area that contains actual\n"
675 " // Remove this 'ack once we have a better way to stop this thing from\n"
677 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
678 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
679 " 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 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
682 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
685 "#else // !MODE_REFRACTION\n"
686 "#ifdef MODE_WATER\n"
687 "varying vec2 TexCoord;\n"
688 "varying vec3 EyeVector;\n"
689 "varying vec4 ModelViewProjectionPosition;\n"
690 "#ifdef VERTEX_SHADER\n"
691 "uniform vec3 EyePosition;\n"
692 "uniform mat4 TexMatrix;\n"
696 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
697 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
698 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
699 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
700 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
701 " gl_Position = ftransform();\n"
702 " ModelViewProjectionPosition = gl_Position;\n"
706 "#ifdef FRAGMENT_SHADER\n"
707 "uniform sampler2D Texture_Normal;\n"
708 "uniform sampler2D Texture_Refraction;\n"
709 "uniform sampler2D Texture_Reflection;\n"
711 "uniform vec4 DistortScaleRefractReflect;\n"
712 "uniform vec4 ScreenScaleRefractReflect;\n"
713 "uniform vec4 ScreenCenterRefractReflect;\n"
714 "uniform vec4 RefractColor;\n"
715 "uniform vec4 ReflectColor;\n"
716 "uniform float ReflectFactor;\n"
717 "uniform float ReflectOffset;\n"
721 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
722 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
723 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
724 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
725 " // FIXME temporary hack to detect the case that the reflection\n"
726 " // gets blackened at edges due to leaving the area that contains actual\n"
728 " // Remove this 'ack once we have a better way to stop this thing from\n"
730 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
731 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
732 " 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 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
735 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
736 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\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 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
740 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
741 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
744 "#else // !MODE_WATER\n"
746 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
747 "# extension GL_ARB_texture_rectangle : enable\n"
750 "#ifdef USESHADOWMAP2D\n"
751 "# ifdef GL_EXT_gpu_shader4\n"
752 "# extension GL_EXT_gpu_shader4 : enable\n"
754 "# ifdef GL_ARB_texture_gather\n"
755 "# extension GL_ARB_texture_gather : enable\n"
757 "# ifdef GL_AMD_texture_texture4\n"
758 "# extension GL_AMD_texture_texture4 : enable\n"
763 "#ifdef USESHADOWMAPCUBE\n"
764 "# extension GL_EXT_gpu_shader4 : enable\n"
767 "#ifdef USESHADOWSAMPLER\n"
768 "# extension GL_ARB_shadow : enable\n"
771 "// common definitions between vertex shader and fragment shader:\n"
773 "//#ifdef __GLSL_CG_DATA_TYPES\n"
774 "//# define myhalf half\n"
775 "//# define myhalf2 half2\n"
776 "//# define myhalf3half3\n"
777 "//# define myhalf4 half4\n"
779 "# define myhalf float\n"
780 "# define myhalf2 vec2\n"
781 "# define myhalf3 vec3\n"
782 "# define myhalf4 vec4\n"
785 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
789 "varying vec2 TexCoord;\n"
790 "#ifdef USEVERTEXTEXTUREBLEND\n"
791 "varying vec2 TexCoord2;\n"
793 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
794 "#define USELIGHTMAP\n"
795 "varying vec2 TexCoordLightmap;\n"
798 "#ifdef MODE_LIGHTSOURCE\n"
799 "varying vec3 CubeVector;\n"
802 "#ifdef MODE_LIGHTSOURCE\n"
803 "varying vec3 LightVector;\n"
805 "#if defined(MODE_LIGHTDIRECTION)\n"
806 "varying vec3 LightVector;\n"
809 "#if defined(USEOFFSETMAPPING) || defined(USESPECULAR)\n"
810 "//#if defined(USEOFFSETMAPPING) || defined(USESPECULAR) || defined(MODE_LIGHTDIRECTION) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
811 "#define USEEYEVECTOR\n"
812 "varying vec3 EyeVector;\n"
815 "varying vec3 EyeVectorModelSpace;\n"
816 "varying float FogPlaneVertexDist;\n"
819 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
820 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
821 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
822 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
825 "#ifdef USEREFLECTION\n"
826 "varying vec4 ModelViewProjectionPosition;\n"
828 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
829 "uniform vec3 LightPosition;\n"
830 "varying vec4 ModelViewPosition;\n"
833 "#ifdef MODE_LIGHTSOURCE\n"
834 "uniform vec3 LightPosition;\n"
836 "uniform vec3 EyePosition;\n"
837 "#ifdef MODE_LIGHTDIRECTION\n"
838 "uniform vec3 LightDir;\n"
840 "uniform vec4 FogPlane;\n"
846 "// vertex shader specific:\n"
847 "#ifdef VERTEX_SHADER\n"
849 "// 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"
851 "#ifdef MODE_DEFERREDGEOMETRY\n"
852 "uniform mat4 TexMatrix;\n"
853 "#ifdef USEVERTEXTEXTUREBLEND\n"
854 "uniform mat4 BackgroundTexMatrix;\n"
858 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
859 "#ifdef USEVERTEXTEXTUREBLEND\n"
860 " gl_FrontColor = gl_Color;\n"
861 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
864 " // transform unnormalized eye direction into tangent space\n"
865 "#ifdef USEOFFSETMAPPING\n"
866 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
867 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
868 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
869 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
872 " VectorS = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz).xyz;\n"
873 " VectorT = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz).xyz;\n"
874 " VectorR = normalize(gl_NormalMatrix * gl_MultiTexCoord3.xyz).xyz;\n"
875 " gl_Position = ftransform();\n"
877 "#else // !MODE_DEFERREDGEOMETRY\n"
878 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
881 " ModelViewPosition = gl_ModelViewMatrix * gl_Vertex;\n"
882 " gl_Position = ftransform();\n"
884 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
885 "uniform mat4 TexMatrix;\n"
886 "#ifdef USEVERTEXTEXTUREBLEND\n"
887 "uniform mat4 BackgroundTexMatrix;\n"
889 "#ifdef MODE_LIGHTSOURCE\n"
890 "uniform mat4 ModelToLight;\n"
894 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
895 " gl_FrontColor = gl_Color;\n"
897 " // copy the surface texcoord\n"
898 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
899 "#ifdef USEVERTEXTEXTUREBLEND\n"
900 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
902 "#ifdef USELIGHTMAP\n"
903 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
906 "#ifdef MODE_LIGHTSOURCE\n"
907 " // transform vertex position into light attenuation/cubemap space\n"
908 " // (-1 to +1 across the light box)\n"
909 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
911 "# ifdef USEDIFFUSE\n"
912 " // transform unnormalized light direction into tangent space\n"
913 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
914 " // normalize it per pixel)\n"
915 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
916 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
917 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
918 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
922 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
923 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
924 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
925 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
928 " // transform unnormalized eye direction into tangent space\n"
929 "#ifdef USEEYEVECTOR\n"
931 " vec3 EyeVectorModelSpace;\n"
933 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
934 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
935 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
936 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
940 "#ifndef USEEYEVECTOR\n"
941 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
943 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
946 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
947 " VectorS = gl_MultiTexCoord1.xyz;\n"
948 " VectorT = gl_MultiTexCoord2.xyz;\n"
949 " VectorR = gl_MultiTexCoord3.xyz;\n"
952 "//#if defined(USEREFLECTION)\n"
953 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
954 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
955 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
958 "// transform vertex to camera space, using ftransform to match non-VS\n"
960 " gl_Position = ftransform();\n"
962 "#ifdef USEREFLECTION\n"
963 " ModelViewProjectionPosition = gl_Position;\n"
966 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
967 "#endif // !MODE_DEFERREDGEOMETRY\n"
969 "#endif // VERTEX_SHADER\n"
974 "// fragment shader specific:\n"
975 "#ifdef FRAGMENT_SHADER\n"
977 "uniform sampler2D Texture_Normal;\n"
978 "uniform sampler2D Texture_Color;\n"
979 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
980 "uniform sampler2D Texture_Gloss;\n"
983 "uniform sampler2D Texture_Glow;\n"
985 "#ifdef USEVERTEXTEXTUREBLEND\n"
986 "uniform sampler2D Texture_SecondaryNormal;\n"
987 "uniform sampler2D Texture_SecondaryColor;\n"
988 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
989 "uniform sampler2D Texture_SecondaryGloss;\n"
992 "uniform sampler2D Texture_SecondaryGlow;\n"
995 "#ifdef USECOLORMAPPING\n"
996 "uniform sampler2D Texture_Pants;\n"
997 "uniform sampler2D Texture_Shirt;\n"
1000 "uniform sampler2D Texture_FogMask;\n"
1002 "#ifdef USELIGHTMAP\n"
1003 "uniform sampler2D Texture_Lightmap;\n"
1005 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1006 "uniform sampler2D Texture_Deluxemap;\n"
1008 "#ifdef USEREFLECTION\n"
1009 "uniform sampler2D Texture_Reflection;\n"
1012 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1013 "uniform sampler2DRect Texture_ScreenDepth;\n"
1014 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
1016 "#ifdef USEDEFERREDLIGHTMAP\n"
1017 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
1018 "uniform sampler2DRect Texture_ScreenSpecular;\n"
1021 "uniform myhalf3 Color_Pants;\n"
1022 "uniform myhalf3 Color_Shirt;\n"
1023 "uniform myhalf3 FogColor;\n"
1026 "uniform float FogRangeRecip;\n"
1027 "uniform float FogPlaneViewDist;\n"
1028 "uniform float FogHeightFade;\n"
1029 "myhalf FogVertex(void)\n"
1032 "#ifdef USEFOGOUTSIDE\n"
1033 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1035 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1037 " return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1041 "#ifdef USEOFFSETMAPPING\n"
1042 "uniform float OffsetMapping_Scale;\n"
1043 "vec2 OffsetMapping(vec2 TexCoord)\n"
1045 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1046 " // 14 sample relief mapping: linear search and then binary search\n"
1047 " // this basically steps forward a small amount repeatedly until it finds\n"
1048 " // itself inside solid, then jitters forward and back using decreasing\n"
1049 " // amounts to find the impact\n"
1050 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1051 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1052 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1053 " vec3 RT = vec3(TexCoord, 1);\n"
1054 " OffsetVector *= 0.1;\n"
1055 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1056 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
1065 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1066 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1067 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1068 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1071 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1072 " // this basically moves forward the full distance, and then backs up based\n"
1073 " // on height of samples\n"
1074 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1075 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1076 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1077 " TexCoord += OffsetVector;\n"
1078 " OffsetVector *= 0.333;\n"
1079 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1080 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1081 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1082 " return TexCoord;\n"
1085 "#endif // USEOFFSETMAPPING\n"
1087 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1088 "uniform sampler2D Texture_Attenuation;\n"
1089 "uniform samplerCube Texture_Cube;\n"
1091 "#ifdef USESHADOWMAPRECT\n"
1092 "# ifdef USESHADOWSAMPLER\n"
1093 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1095 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1099 "#ifdef USESHADOWMAP2D\n"
1100 "# ifdef USESHADOWSAMPLER\n"
1101 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1103 "uniform sampler2D Texture_ShadowMap2D;\n"
1107 "#ifdef USESHADOWMAPVSDCT\n"
1108 "uniform samplerCube Texture_CubeProjection;\n"
1111 "#ifdef USESHADOWMAPCUBE\n"
1112 "# ifdef USESHADOWSAMPLER\n"
1113 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1115 "uniform samplerCube Texture_ShadowMapCube;\n"
1119 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1120 "uniform vec2 ShadowMap_TextureScale;\n"
1121 "uniform vec4 ShadowMap_Parameters;\n"
1124 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1125 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1127 " vec3 adir = abs(dir);\n"
1128 "# ifndef USESHADOWMAPVSDCT\n"
1132 " if (adir.x > adir.y)\n"
1134 " if (adir.x > adir.z) // X\n"
1138 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1144 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1149 " if (adir.y > adir.z) // Y\n"
1153 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1159 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1163 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1164 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1165 " stc.z += ShadowMap_Parameters.z;\n"
1168 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1169 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1170 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1171 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1172 " stc.z += ShadowMap_Parameters.z;\n"
1176 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1178 "#ifdef USESHADOWMAPCUBE\n"
1179 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1181 " vec3 adir = abs(dir);\n"
1182 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1186 "# ifdef USESHADOWMAPRECT\n"
1187 "float ShadowMapCompare(vec3 dir)\n"
1189 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1191 "# ifdef USESHADOWSAMPLER\n"
1193 "# ifdef USESHADOWMAPPCF\n"
1194 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1195 " 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"
1197 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1202 "# ifdef USESHADOWMAPPCF\n"
1203 "# if USESHADOWMAPPCF > 1\n"
1204 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1205 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1206 " 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"
1207 " 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"
1208 " 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"
1209 " 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"
1210 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1211 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1213 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1214 " vec2 offset = fract(shadowmaptc.xy);\n"
1215 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1216 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1217 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1218 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1219 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1222 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1230 "# ifdef USESHADOWMAP2D\n"
1231 "float ShadowMapCompare(vec3 dir)\n"
1233 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1236 "# ifdef USESHADOWSAMPLER\n"
1237 "# ifdef USESHADOWMAPPCF\n"
1238 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1239 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1240 " 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"
1242 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1245 "# ifdef USESHADOWMAPPCF\n"
1246 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1247 "# ifdef GL_ARB_texture_gather\n"
1248 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1250 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1252 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1253 " center *= ShadowMap_TextureScale;\n"
1254 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1255 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1256 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1257 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1258 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1259 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1260 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1262 "# ifdef GL_EXT_gpu_shader4\n"
1263 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1265 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1267 "# if USESHADOWMAPPCF > 1\n"
1268 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1269 " center *= ShadowMap_TextureScale;\n"
1270 " 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"
1271 " 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"
1272 " 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"
1273 " 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"
1274 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1275 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1277 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1278 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1279 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1280 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1281 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1282 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1286 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1293 "# ifdef USESHADOWMAPCUBE\n"
1294 "float ShadowMapCompare(vec3 dir)\n"
1296 " // apply depth texture cubemap as light filter\n"
1297 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1299 "# ifdef USESHADOWSAMPLER\n"
1300 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1302 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1307 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1309 "#ifdef MODE_DEFERREDGEOMETRY\n"
1312 "#ifdef USEOFFSETMAPPING\n"
1313 " // apply offsetmapping\n"
1314 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1315 "#define TexCoord TexCoordOffset\n"
1318 "#ifdef USEALPHAKILL\n"
1319 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1323 "#ifdef USEVERTEXTEXTUREBLEND\n"
1324 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1325 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1326 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1327 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1330 "#ifdef USEVERTEXTEXTUREBLEND\n"
1331 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1333 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1336 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1338 "#else // !MODE_DEFERREDGEOMETRY\n"
1339 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1340 "uniform mat4 ViewToLight;\n"
1341 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1342 "uniform vec2 ScreenToDepth;\n"
1343 "uniform myhalf3 DeferredColor_Ambient;\n"
1344 "uniform myhalf3 DeferredColor_Diffuse;\n"
1345 "#ifdef USESPECULAR\n"
1346 "uniform myhalf3 DeferredColor_Specular;\n"
1347 "uniform myhalf SpecularPower;\n"
1351 " // calculate viewspace pixel position\n"
1353 " position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1354 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1355 " // decode viewspace pixel normal\n"
1356 " myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1357 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1358 " // surfacenormal = pixel normal in viewspace\n"
1359 " // LightVector = pixel to light in viewspace\n"
1360 " // CubeVector = position in lightspace\n"
1361 " // eyevector = pixel to view in viewspace\n"
1362 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1363 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1364 "#ifdef USEDIFFUSE\n"
1365 " // calculate diffuse shading\n"
1366 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1367 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1369 "#ifdef USESPECULAR\n"
1370 " // calculate directional shading\n"
1371 " vec3 eyevector = position * -1.0;\n"
1372 "# ifdef USEEXACTSPECULARMATH\n"
1373 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1375 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1376 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1380 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1381 " fade *= ShadowMapCompare(CubeVector);\n"
1384 "#ifdef USEDIFFUSE\n"
1385 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1387 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1389 "#ifdef USESPECULAR\n"
1390 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1392 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1395 "# ifdef USECUBEFILTER\n"
1396 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1397 " gl_FragData[0] *= cubecolor;\n"
1398 " gl_FragData[1] *= cubecolor;\n"
1401 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1402 "#ifdef USEDEFERREDLIGHTMAP\n"
1403 "uniform myhalf3 DeferredMod_Diffuse;\n"
1404 "uniform myhalf3 DeferredMod_Specular;\n"
1406 "uniform myhalf3 Color_Ambient;\n"
1407 "uniform myhalf3 Color_Diffuse;\n"
1408 "uniform myhalf3 Color_Specular;\n"
1409 "uniform myhalf SpecularPower;\n"
1411 "uniform myhalf3 Color_Glow;\n"
1413 "uniform myhalf Alpha;\n"
1414 "#ifdef USEREFLECTION\n"
1415 "uniform vec4 DistortScaleRefractReflect;\n"
1416 "uniform vec4 ScreenScaleRefractReflect;\n"
1417 "uniform vec4 ScreenCenterRefractReflect;\n"
1418 "uniform myhalf4 ReflectColor;\n"
1420 "#ifdef MODE_LIGHTDIRECTION\n"
1421 "uniform myhalf3 LightColor;\n"
1423 "#ifdef MODE_LIGHTSOURCE\n"
1424 "uniform myhalf3 LightColor;\n"
1428 "#ifdef USEOFFSETMAPPING\n"
1429 " // apply offsetmapping\n"
1430 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1431 "#define TexCoord TexCoordOffset\n"
1434 " // combine the diffuse textures (base, pants, shirt)\n"
1435 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1436 "#ifdef USEALPHAKILL\n"
1437 " if (color.a < 0.5)\n"
1440 " color.a *= Alpha;\n"
1441 "#ifdef USECOLORMAPPING\n"
1442 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1444 "#ifdef USEVERTEXTEXTUREBLEND\n"
1445 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1446 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1447 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1448 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1450 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1453 " // get the surface normal\n"
1454 "#ifdef USEVERTEXTEXTUREBLEND\n"
1455 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1457 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1460 " // get the material colors\n"
1461 " myhalf3 diffusetex = color.rgb;\n"
1462 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1463 "# ifdef USEVERTEXTEXTUREBLEND\n"
1464 " myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1466 " myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1473 "#ifdef MODE_LIGHTSOURCE\n"
1474 " // light source\n"
1475 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1476 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1477 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1478 "#ifdef USESPECULAR\n"
1479 "#ifdef USEEXACTSPECULARMATH\n"
1480 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1482 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1483 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1485 " color.rgb += glosstex * (specular * Color_Specular);\n"
1487 " color.rgb *= LightColor;\n"
1488 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1489 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1490 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1492 "# ifdef USECUBEFILTER\n"
1493 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1495 "#endif // MODE_LIGHTSOURCE\n"
1500 "#ifdef MODE_LIGHTDIRECTION\n"
1502 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1503 "#define lightcolor LightColor\n"
1504 "#endif // MODE_LIGHTDIRECTION\n"
1505 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1507 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1508 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1509 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1510 " // convert modelspace light vector to tangentspace\n"
1511 " myhalf3 lightnormal;\n"
1512 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1513 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1514 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1515 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1516 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1517 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1518 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1519 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1520 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1521 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1522 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1523 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1524 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1525 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1526 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1528 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1529 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1530 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1536 "#ifdef MODE_LIGHTMAP\n"
1537 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1538 "#endif // MODE_LIGHTMAP\n"
1539 "#ifdef MODE_VERTEXCOLOR\n"
1540 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1541 "#endif // MODE_VERTEXCOLOR\n"
1542 "#ifdef MODE_FLATCOLOR\n"
1543 " color.rgb = diffusetex * Color_Ambient;\n"
1544 "#endif // MODE_FLATCOLOR\n"
1550 "# ifdef USEDIFFUSE\n"
1551 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1552 "# ifdef USESPECULAR\n"
1553 "# ifdef USEEXACTSPECULARMATH\n"
1554 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1556 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1557 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1559 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1561 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1564 " color.rgb = diffusetex * Color_Ambient;\n"
1568 "#ifdef USEDEFERREDLIGHTMAP\n"
1569 " color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1570 " color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1574 "#ifdef USEVERTEXTEXTUREBLEND\n"
1575 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1577 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1582 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1585 " // 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"
1586 "#ifdef USEREFLECTION\n"
1587 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1588 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1589 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1590 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1591 " // FIXME temporary hack to detect the case that the reflection\n"
1592 " // gets blackened at edges due to leaving the area that contains actual\n"
1594 " // Remove this 'ack once we have a better way to stop this thing from\n"
1596 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1597 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1598 " 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 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1601 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1604 " gl_FragColor = vec4(color);\n"
1606 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1607 "#endif // !MODE_DEFERREDGEOMETRY\n"
1609 "#endif // FRAGMENT_SHADER\n"
1611 "#endif // !MODE_WATER\n"
1612 "#endif // !MODE_REFRACTION\n"
1613 "#endif // !MODE_BLOOMBLUR\n"
1614 "#endif // !MODE_GENERIC\n"
1615 "#endif // !MODE_POSTPROCESS\n"
1616 "#endif // !MODE_SHOWDEPTH\n"
1617 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1620 typedef struct shaderpermutationinfo_s
1622 const char *pretext;
1625 shaderpermutationinfo_t;
1627 typedef struct shadermodeinfo_s
1629 const char *vertexfilename;
1630 const char *geometryfilename;
1631 const char *fragmentfilename;
1632 const char *pretext;
1637 typedef enum shaderpermutation_e
1639 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1640 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1641 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1642 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1643 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1644 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1645 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1646 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1647 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1648 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1649 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1650 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1651 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1652 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1653 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1654 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1655 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1656 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1657 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1658 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1659 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1660 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1661 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1662 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1663 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1664 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
1665 SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
1666 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
1668 shaderpermutation_t;
1670 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1671 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1673 {"#define USEDIFFUSE\n", " diffuse"},
1674 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1675 {"#define USEVIEWTINT\n", " viewtint"},
1676 {"#define USECOLORMAPPING\n", " colormapping"},
1677 {"#define USESATURATION\n", " saturation"},
1678 {"#define USEFOGINSIDE\n", " foginside"},
1679 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1680 {"#define USEGAMMARAMPS\n", " gammaramps"},
1681 {"#define USECUBEFILTER\n", " cubefilter"},
1682 {"#define USEGLOW\n", " glow"},
1683 {"#define USEBLOOM\n", " bloom"},
1684 {"#define USESPECULAR\n", " specular"},
1685 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1686 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1687 {"#define USEREFLECTION\n", " reflection"},
1688 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1689 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1690 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1691 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1692 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1693 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1694 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1695 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1696 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1697 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1698 {"#define USEALPHAKILL\n", " alphakill"},
1701 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1702 typedef enum shadermode_e
1704 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1705 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1706 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1707 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1708 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1709 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1710 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1711 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1712 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1713 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1714 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1715 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1716 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1717 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1718 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1723 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1724 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1726 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1727 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1728 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1729 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1730 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1731 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1732 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1733 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1734 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1735 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1736 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1737 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1738 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1739 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1740 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1743 struct r_glsl_permutation_s;
1744 typedef struct r_glsl_permutation_s
1746 /// hash lookup data
1747 struct r_glsl_permutation_s *hashnext;
1749 unsigned int permutation;
1751 /// indicates if we have tried compiling this permutation already
1753 /// 0 if compilation failed
1755 /// locations of detected uniforms in program object, or -1 if not found
1756 int loc_Texture_First;
1757 int loc_Texture_Second;
1758 int loc_Texture_GammaRamps;
1759 int loc_Texture_Normal;
1760 int loc_Texture_Color;
1761 int loc_Texture_Gloss;
1762 int loc_Texture_Glow;
1763 int loc_Texture_SecondaryNormal;
1764 int loc_Texture_SecondaryColor;
1765 int loc_Texture_SecondaryGloss;
1766 int loc_Texture_SecondaryGlow;
1767 int loc_Texture_Pants;
1768 int loc_Texture_Shirt;
1769 int loc_Texture_FogMask;
1770 int loc_Texture_Lightmap;
1771 int loc_Texture_Deluxemap;
1772 int loc_Texture_Attenuation;
1773 int loc_Texture_Cube;
1774 int loc_Texture_Refraction;
1775 int loc_Texture_Reflection;
1776 int loc_Texture_ShadowMapRect;
1777 int loc_Texture_ShadowMapCube;
1778 int loc_Texture_ShadowMap2D;
1779 int loc_Texture_CubeProjection;
1780 int loc_Texture_ScreenDepth;
1781 int loc_Texture_ScreenNormalMap;
1782 int loc_Texture_ScreenDiffuse;
1783 int loc_Texture_ScreenSpecular;
1785 int loc_BloomBlur_Parameters;
1787 int loc_Color_Ambient;
1788 int loc_Color_Diffuse;
1789 int loc_Color_Specular;
1791 int loc_Color_Pants;
1792 int loc_Color_Shirt;
1793 int loc_DeferredColor_Ambient;
1794 int loc_DeferredColor_Diffuse;
1795 int loc_DeferredColor_Specular;
1796 int loc_DeferredMod_Diffuse;
1797 int loc_DeferredMod_Specular;
1798 int loc_DistortScaleRefractReflect;
1799 int loc_EyePosition;
1801 int loc_FogHeightFade;
1803 int loc_FogPlaneViewDist;
1804 int loc_FogRangeRecip;
1807 int loc_LightPosition;
1808 int loc_OffsetMapping_Scale;
1810 int loc_ReflectColor;
1811 int loc_ReflectFactor;
1812 int loc_ReflectOffset;
1813 int loc_RefractColor;
1815 int loc_ScreenCenterRefractReflect;
1816 int loc_ScreenScaleRefractReflect;
1817 int loc_ScreenToDepth;
1818 int loc_ShadowMap_Parameters;
1819 int loc_ShadowMap_TextureScale;
1820 int loc_SpecularPower;
1825 int loc_ViewTintColor;
1826 int loc_ViewToLight;
1827 int loc_ModelToLight;
1829 int loc_BackgroundTexMatrix;
1831 r_glsl_permutation_t;
1833 #define SHADERPERMUTATION_HASHSIZE 256
1835 /// information about each possible shader permutation
1836 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1837 /// currently selected permutation
1838 r_glsl_permutation_t *r_glsl_permutation;
1839 /// storage for permutations linked in the hash table
1840 memexpandablearray_t r_glsl_permutationarray;
1842 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1844 //unsigned int hashdepth = 0;
1845 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1846 r_glsl_permutation_t *p;
1847 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1849 if (p->mode == mode && p->permutation == permutation)
1851 //if (hashdepth > 10)
1852 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1857 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1859 p->permutation = permutation;
1860 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1861 r_glsl_permutationhash[mode][hashindex] = p;
1862 //if (hashdepth > 10)
1863 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1867 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1870 if (!filename || !filename[0])
1872 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1875 if (printfromdisknotice)
1876 Con_DPrintf("from disk %s... ", filename);
1877 return shaderstring;
1879 else if (!strcmp(filename, "glsl/default.glsl"))
1881 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1882 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1884 return shaderstring;
1887 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1890 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1891 int vertstrings_count = 0;
1892 int geomstrings_count = 0;
1893 int fragstrings_count = 0;
1894 char *vertexstring, *geometrystring, *fragmentstring;
1895 const char *vertstrings_list[32+3];
1896 const char *geomstrings_list[32+3];
1897 const char *fragstrings_list[32+3];
1898 char permutationname[256];
1905 permutationname[0] = 0;
1906 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1907 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1908 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1910 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1912 // the first pretext is which type of shader to compile as
1913 // (later these will all be bound together as a program object)
1914 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1915 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1916 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1918 // the second pretext is the mode (for example a light source)
1919 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1920 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1921 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1922 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1924 // now add all the permutation pretexts
1925 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1927 if (permutation & (1<<i))
1929 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1930 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1931 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1932 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1936 // keep line numbers correct
1937 vertstrings_list[vertstrings_count++] = "\n";
1938 geomstrings_list[geomstrings_count++] = "\n";
1939 fragstrings_list[fragstrings_count++] = "\n";
1943 // now append the shader text itself
1944 vertstrings_list[vertstrings_count++] = vertexstring;
1945 geomstrings_list[geomstrings_count++] = geometrystring;
1946 fragstrings_list[fragstrings_count++] = fragmentstring;
1948 // if any sources were NULL, clear the respective list
1950 vertstrings_count = 0;
1951 if (!geometrystring)
1952 geomstrings_count = 0;
1953 if (!fragmentstring)
1954 fragstrings_count = 0;
1956 // compile the shader program
1957 if (vertstrings_count + geomstrings_count + fragstrings_count)
1958 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1962 qglUseProgramObjectARB(p->program);CHECKGLERROR
1963 // look up all the uniform variable names we care about, so we don't
1964 // have to look them up every time we set them
1966 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1967 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1968 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1969 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1970 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1971 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1972 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1973 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1974 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1975 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1976 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1977 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1978 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1979 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1980 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1981 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1982 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1983 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1984 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1985 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1986 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1987 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1988 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1989 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1990 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
1991 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
1992 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
1993 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
1994 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
1995 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
1996 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1997 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
1998 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
1999 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
2000 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
2001 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
2002 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
2003 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
2004 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
2005 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
2006 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
2007 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
2008 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
2009 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
2010 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
2011 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
2012 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
2013 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
2014 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
2015 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
2016 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
2017 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
2018 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
2019 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
2020 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
2021 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
2022 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
2023 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
2024 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
2025 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
2026 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2027 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2028 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2029 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2030 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
2031 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
2032 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
2033 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
2034 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
2035 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
2036 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
2037 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
2038 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
2039 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
2040 // initialize the samplers to refer to the texture units we use
2041 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
2042 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
2043 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
2044 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
2045 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
2046 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
2047 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
2048 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2049 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2050 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2051 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
2052 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
2053 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
2054 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
2055 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
2056 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
2057 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
2058 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
2059 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
2060 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
2061 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
2062 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
2063 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
2064 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2065 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
2066 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2067 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
2068 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2070 if (developer.integer)
2071 Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2074 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
2078 Mem_Free(vertexstring);
2080 Mem_Free(geometrystring);
2082 Mem_Free(fragmentstring);
2085 void R_GLSL_Restart_f(void)
2087 unsigned int i, limit;
2088 r_glsl_permutation_t *p;
2089 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2090 for (i = 0;i < limit;i++)
2092 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2094 GL_Backend_FreeProgram(p->program);
2095 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2098 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2101 void R_GLSL_DumpShader_f(void)
2105 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2108 Con_Printf("failed to write to glsl/default.glsl\n");
2112 FS_Print(file, "/* The engine may define the following macros:\n");
2113 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2114 for (i = 0;i < SHADERMODE_COUNT;i++)
2115 FS_Print(file, shadermodeinfo[i].pretext);
2116 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2117 FS_Print(file, shaderpermutationinfo[i].pretext);
2118 FS_Print(file, "*/\n");
2119 FS_Print(file, builtinshaderstring);
2122 Con_Printf("glsl/default.glsl written\n");
2125 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
2127 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2128 if (r_glsl_permutation != perm)
2130 r_glsl_permutation = perm;
2131 if (!r_glsl_permutation->program)
2133 if (!r_glsl_permutation->compiled)
2134 R_GLSL_CompilePermutation(perm, mode, permutation);
2135 if (!r_glsl_permutation->program)
2137 // remove features until we find a valid permutation
2139 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2141 // reduce i more quickly whenever it would not remove any bits
2142 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2143 if (!(permutation & j))
2146 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2147 if (!r_glsl_permutation->compiled)
2148 R_GLSL_CompilePermutation(perm, mode, permutation);
2149 if (r_glsl_permutation->program)
2152 if (i >= SHADERPERMUTATION_COUNT)
2154 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2155 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2156 qglUseProgramObjectARB(0);CHECKGLERROR
2157 return; // no bit left to clear, entire mode is broken
2162 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2166 void R_SetupGenericShader(qboolean usetexture)
2168 switch(vid.renderpath)
2170 case RENDERPATH_GL20:
2171 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
2173 case RENDERPATH_GL13:
2174 case RENDERPATH_GL11:
2179 void R_SetupGenericTwoTextureShader(int texturemode)
2181 switch (vid.renderpath)
2183 case RENDERPATH_GL20:
2184 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))));
2186 case RENDERPATH_GL13:
2187 case RENDERPATH_GL11:
2188 R_Mesh_TexCombine(1, GL_DECAL, GL_DECAL, 1, 1);
2193 void R_SetupDepthOrShadowShader(void)
2195 switch (vid.renderpath)
2197 case RENDERPATH_GL20:
2198 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
2200 case RENDERPATH_GL13:
2202 case RENDERPATH_GL11:
2207 void R_SetupShowDepthShader(void)
2209 switch (vid.renderpath)
2211 case RENDERPATH_GL20:
2212 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
2214 case RENDERPATH_GL13:
2216 case RENDERPATH_GL11:
2221 extern qboolean r_shadow_usingdeferredprepass;
2222 extern cvar_t r_shadow_deferred_8bitrange;
2223 extern rtexture_t *r_shadow_attenuationgradienttexture;
2224 extern rtexture_t *r_shadow_attenuation2dtexture;
2225 extern rtexture_t *r_shadow_attenuation3dtexture;
2226 extern qboolean r_shadow_usingshadowmaprect;
2227 extern qboolean r_shadow_usingshadowmapcube;
2228 extern qboolean r_shadow_usingshadowmap2d;
2229 extern float r_shadow_shadowmap_texturescale[2];
2230 extern float r_shadow_shadowmap_parameters[4];
2231 extern qboolean r_shadow_shadowmapvsdct;
2232 extern qboolean r_shadow_shadowmapsampler;
2233 extern int r_shadow_shadowmappcf;
2234 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2236 // select a permutation of the lighting shader appropriate to this
2237 // combination of texture, entity, light source, and fogging, only use the
2238 // minimum features necessary to avoid wasting rendering time in the
2239 // fragment shader on features that are not being used
2240 unsigned int permutation = 0;
2241 unsigned int mode = 0;
2243 // TODO: implement geometry-shader based shadow volumes someday
2244 if (r_glsl_offsetmapping.integer)
2246 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2247 if (r_glsl_offsetmapping_reliefmapping.integer)
2248 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2250 if (rsurfacepass == RSURFPASS_BACKGROUND)
2252 // distorted background
2253 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2254 mode = SHADERMODE_WATER;
2256 mode = SHADERMODE_REFRACTION;
2258 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2260 // normalmap (deferred prepass), may use alpha test on diffuse
2261 mode = SHADERMODE_DEFERREDGEOMETRY;
2262 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2263 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2264 if (r_glsl_offsetmapping.integer)
2266 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2267 if (r_glsl_offsetmapping_reliefmapping.integer)
2268 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2271 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2274 mode = SHADERMODE_LIGHTSOURCE;
2275 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2276 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2277 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2278 permutation |= SHADERPERMUTATION_CUBEFILTER;
2279 if (diffusescale > 0)
2280 permutation |= SHADERPERMUTATION_DIFFUSE;
2281 if (specularscale > 0)
2282 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2283 if (r_refdef.fogenabled)
2284 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2285 if (rsurface.texture->colormapping)
2286 permutation |= SHADERPERMUTATION_COLORMAPPING;
2287 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2289 if (r_shadow_usingshadowmaprect)
2290 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2291 if (r_shadow_usingshadowmap2d)
2292 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2293 if (r_shadow_usingshadowmapcube)
2294 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2295 else if(r_shadow_shadowmapvsdct)
2296 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2298 if (r_shadow_shadowmapsampler)
2299 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2300 if (r_shadow_shadowmappcf > 1)
2301 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2302 else if (r_shadow_shadowmappcf)
2303 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2306 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2308 // unshaded geometry (fullbright or ambient model lighting)
2309 mode = SHADERMODE_FLATCOLOR;
2310 ambientscale = diffusescale = specularscale = 0;
2311 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2312 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2313 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2314 permutation |= SHADERPERMUTATION_GLOW;
2315 if (r_refdef.fogenabled)
2316 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2317 if (rsurface.texture->colormapping)
2318 permutation |= SHADERPERMUTATION_COLORMAPPING;
2319 if (r_glsl_offsetmapping.integer)
2321 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2322 if (r_glsl_offsetmapping_reliefmapping.integer)
2323 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2325 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2326 permutation |= SHADERPERMUTATION_REFLECTION;
2328 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2330 // directional model lighting
2331 mode = SHADERMODE_LIGHTDIRECTION;
2332 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2333 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2334 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2335 permutation |= SHADERPERMUTATION_GLOW;
2336 permutation |= SHADERPERMUTATION_DIFFUSE;
2337 if (specularscale > 0)
2338 permutation |= SHADERPERMUTATION_SPECULAR;
2339 if (r_refdef.fogenabled)
2340 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2341 if (rsurface.texture->colormapping)
2342 permutation |= SHADERPERMUTATION_COLORMAPPING;
2343 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2344 permutation |= SHADERPERMUTATION_REFLECTION;
2345 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2346 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2348 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2350 // ambient model lighting
2351 mode = SHADERMODE_LIGHTDIRECTION;
2352 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2353 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2354 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2355 permutation |= SHADERPERMUTATION_GLOW;
2356 if (r_refdef.fogenabled)
2357 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2358 if (rsurface.texture->colormapping)
2359 permutation |= SHADERPERMUTATION_COLORMAPPING;
2360 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2361 permutation |= SHADERPERMUTATION_REFLECTION;
2362 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2363 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2368 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2370 // deluxemapping (light direction texture)
2371 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2372 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2374 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2375 permutation |= SHADERPERMUTATION_DIFFUSE;
2376 if (specularscale > 0)
2377 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2379 else if (r_glsl_deluxemapping.integer >= 2)
2381 // fake deluxemapping (uniform light direction in tangentspace)
2382 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2383 permutation |= SHADERPERMUTATION_DIFFUSE;
2384 if (specularscale > 0)
2385 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2387 else if (rsurface.uselightmaptexture)
2389 // ordinary lightmapping (q1bsp, q3bsp)
2390 mode = SHADERMODE_LIGHTMAP;
2394 // ordinary vertex coloring (q3bsp)
2395 mode = SHADERMODE_VERTEXCOLOR;
2397 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2398 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2399 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2400 permutation |= SHADERPERMUTATION_GLOW;
2401 if (r_refdef.fogenabled)
2402 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2403 if (rsurface.texture->colormapping)
2404 permutation |= SHADERPERMUTATION_COLORMAPPING;
2405 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2406 permutation |= SHADERPERMUTATION_REFLECTION;
2407 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2408 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2410 if(permutation & SHADERPERMUTATION_SPECULAR)
2411 if(r_shadow_glossexact.integer)
2412 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2413 if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
2414 permutation |= SHADERPERMUTATION_ALPHAKILL;
2415 R_SetupShader_SetPermutation(mode, permutation);
2416 if (mode == SHADERMODE_LIGHTSOURCE)
2418 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2419 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2420 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2421 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);
2422 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);
2423 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
2425 // additive passes are only darkened by fog, not tinted
2426 if (r_glsl_permutation->loc_FogColor >= 0)
2427 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2428 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]);
2429 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]);
2430 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2434 if (mode == SHADERMODE_FLATCOLOR)
2436 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
2438 else if (mode == SHADERMODE_LIGHTDIRECTION)
2440 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]);
2441 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
2442 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
2443 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
2444 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2445 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]);
2446 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]);
2450 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]);
2451 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]);
2452 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);
2453 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);
2454 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);
2456 // additive passes are only darkened by fog, not tinted
2457 if (r_glsl_permutation->loc_FogColor >= 0)
2459 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2460 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2462 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2464 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);
2465 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]);
2466 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]);
2467 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2468 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2469 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2470 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2471 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2473 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2474 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2475 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2476 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
2477 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2478 if (r_glsl_permutation->loc_Color_Pants >= 0)
2480 if (rsurface.texture->currentskinframe->pants)
2481 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2483 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2485 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2487 if (rsurface.texture->currentskinframe->shirt)
2488 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2490 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2492 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]);
2493 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2494 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2495 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2496 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2497 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]);
2501 void R_SetupDeferredLightShader(const rtlight_t *rtlight)
2503 // select a permutation of the lighting shader appropriate to this
2504 // combination of texture, entity, light source, and fogging, only use the
2505 // minimum features necessary to avoid wasting rendering time in the
2506 // fragment shader on features that are not being used
2507 unsigned int permutation = 0;
2508 unsigned int mode = 0;
2509 const float *lightcolorbase = rtlight->currentcolor;
2510 float ambientscale = rtlight->ambientscale;
2511 float diffusescale = rtlight->diffusescale;
2512 float specularscale = rtlight->specularscale;
2513 // this is the location of the light in view space
2514 vec3_t viewlightorigin;
2515 // this transforms from view space (camera) to light space (cubemap)
2516 matrix4x4_t viewtolight;
2517 matrix4x4_t lighttoview;
2518 float viewtolight16f[16];
2519 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2521 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2522 if (rtlight->currentcubemap != r_texture_whitecube)
2523 permutation |= SHADERPERMUTATION_CUBEFILTER;
2524 if (diffusescale > 0)
2525 permutation |= SHADERPERMUTATION_DIFFUSE;
2526 if (specularscale > 0)
2528 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2529 if (r_shadow_glossexact.integer)
2530 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2532 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2534 if (r_shadow_usingshadowmaprect)
2535 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2536 if (r_shadow_usingshadowmap2d)
2537 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2538 if (r_shadow_usingshadowmapcube)
2539 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2540 else if(r_shadow_shadowmapvsdct)
2541 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2543 if (r_shadow_shadowmapsampler)
2544 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2545 if (r_shadow_shadowmappcf > 1)
2546 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2547 else if (r_shadow_shadowmappcf)
2548 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2550 R_SetupShader_SetPermutation(mode, permutation);
2551 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2552 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2553 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2554 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2555 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2556 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight, 1, false, viewtolight16f);
2557 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);
2558 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);
2559 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);
2560 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]);
2561 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]);
2562 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));
2563 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]);
2566 #define SKINFRAME_HASH 1024
2570 int loadsequence; // incremented each level change
2571 memexpandablearray_t array;
2572 skinframe_t *hash[SKINFRAME_HASH];
2575 r_skinframe_t r_skinframe;
2577 void R_SkinFrame_PrepareForPurge(void)
2579 r_skinframe.loadsequence++;
2580 // wrap it without hitting zero
2581 if (r_skinframe.loadsequence >= 200)
2582 r_skinframe.loadsequence = 1;
2585 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2589 // mark the skinframe as used for the purging code
2590 skinframe->loadsequence = r_skinframe.loadsequence;
2593 void R_SkinFrame_Purge(void)
2597 for (i = 0;i < SKINFRAME_HASH;i++)
2599 for (s = r_skinframe.hash[i];s;s = s->next)
2601 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2603 if (s->merged == s->base)
2605 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2606 R_PurgeTexture(s->stain );s->stain = NULL;
2607 R_PurgeTexture(s->merged);s->merged = NULL;
2608 R_PurgeTexture(s->base );s->base = NULL;
2609 R_PurgeTexture(s->pants );s->pants = NULL;
2610 R_PurgeTexture(s->shirt );s->shirt = NULL;
2611 R_PurgeTexture(s->nmap );s->nmap = NULL;
2612 R_PurgeTexture(s->gloss );s->gloss = NULL;
2613 R_PurgeTexture(s->glow );s->glow = NULL;
2614 R_PurgeTexture(s->fog );s->fog = NULL;
2615 s->loadsequence = 0;
2621 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2623 char basename[MAX_QPATH];
2625 Image_StripImageExtension(name, basename, sizeof(basename));
2627 if( last == NULL ) {
2629 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2630 item = r_skinframe.hash[hashindex];
2635 // linearly search through the hash bucket
2636 for( ; item ; item = item->next ) {
2637 if( !strcmp( item->basename, basename ) ) {
2644 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2648 char basename[MAX_QPATH];
2650 Image_StripImageExtension(name, basename, sizeof(basename));
2652 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2653 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2654 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2658 rtexture_t *dyntexture;
2659 // check whether its a dynamic texture
2660 dyntexture = CL_GetDynTexture( basename );
2661 if (!add && !dyntexture)
2663 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2664 memset(item, 0, sizeof(*item));
2665 strlcpy(item->basename, basename, sizeof(item->basename));
2666 item->base = dyntexture; // either NULL or dyntexture handle
2667 item->textureflags = textureflags;
2668 item->comparewidth = comparewidth;
2669 item->compareheight = compareheight;
2670 item->comparecrc = comparecrc;
2671 item->next = r_skinframe.hash[hashindex];
2672 r_skinframe.hash[hashindex] = item;
2674 else if( item->base == NULL )
2676 rtexture_t *dyntexture;
2677 // check whether its a dynamic texture
2678 // 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]
2679 dyntexture = CL_GetDynTexture( basename );
2680 item->base = dyntexture; // either NULL or dyntexture handle
2683 R_SkinFrame_MarkUsed(item);
2687 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2689 unsigned long long avgcolor[5], wsum; \
2697 for(pix = 0; pix < cnt; ++pix) \
2700 for(comp = 0; comp < 3; ++comp) \
2702 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2705 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2707 for(comp = 0; comp < 3; ++comp) \
2708 avgcolor[comp] += getpixel * w; \
2711 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2712 avgcolor[4] += getpixel; \
2714 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2716 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2717 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2718 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2719 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2722 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2725 unsigned char *pixels;
2726 unsigned char *bumppixels;
2727 unsigned char *basepixels = NULL;
2728 int basepixels_width;
2729 int basepixels_height;
2730 skinframe_t *skinframe;
2732 if (cls.state == ca_dedicated)
2735 // return an existing skinframe if already loaded
2736 // if loading of the first image fails, don't make a new skinframe as it
2737 // would cause all future lookups of this to be missing
2738 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2739 if (skinframe && skinframe->base)
2742 basepixels = loadimagepixelsbgra(name, complain, true);
2743 if (basepixels == NULL)
2746 if (developer_loading.integer)
2747 Con_Printf("loading skin \"%s\"\n", name);
2749 // we've got some pixels to store, so really allocate this new texture now
2751 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2752 skinframe->stain = NULL;
2753 skinframe->merged = NULL;
2754 skinframe->base = r_texture_notexture;
2755 skinframe->pants = NULL;
2756 skinframe->shirt = NULL;
2757 skinframe->nmap = r_texture_blanknormalmap;
2758 skinframe->gloss = NULL;
2759 skinframe->glow = NULL;
2760 skinframe->fog = NULL;
2761 skinframe->hasalpha = false;
2763 basepixels_width = image_width;
2764 basepixels_height = image_height;
2765 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);
2767 if (textureflags & TEXF_ALPHA)
2769 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2771 if (basepixels[j] < 255)
2773 skinframe->hasalpha = true;
2777 if (r_loadfog && skinframe->hasalpha)
2779 // has transparent pixels
2780 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2781 for (j = 0;j < image_width * image_height * 4;j += 4)
2786 pixels[j+3] = basepixels[j+3];
2788 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);
2793 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2794 //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]);
2796 // _norm is the name used by tenebrae and has been adopted as standard
2797 if (r_loadnormalmap)
2799 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2801 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);
2805 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2807 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2808 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2809 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);
2811 Mem_Free(bumppixels);
2813 else if (r_shadow_bumpscale_basetexture.value > 0)
2815 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2816 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2817 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);
2821 // _luma is supported for tenebrae compatibility
2822 // (I think it's a very stupid name, but oh well)
2823 // _glow is the preferred name
2824 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;}
2825 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;}
2826 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;}
2827 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;}
2830 Mem_Free(basepixels);
2835 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2836 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2839 unsigned char *temp1, *temp2;
2840 skinframe_t *skinframe;
2842 if (cls.state == ca_dedicated)
2845 // if already loaded just return it, otherwise make a new skinframe
2846 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2847 if (skinframe && skinframe->base)
2850 skinframe->stain = NULL;
2851 skinframe->merged = NULL;
2852 skinframe->base = r_texture_notexture;
2853 skinframe->pants = NULL;
2854 skinframe->shirt = NULL;
2855 skinframe->nmap = r_texture_blanknormalmap;
2856 skinframe->gloss = NULL;
2857 skinframe->glow = NULL;
2858 skinframe->fog = NULL;
2859 skinframe->hasalpha = false;
2861 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2865 if (developer_loading.integer)
2866 Con_Printf("loading 32bit skin \"%s\"\n", name);
2868 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
2870 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2871 temp2 = temp1 + width * height * 4;
2872 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2873 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2876 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2877 if (textureflags & TEXF_ALPHA)
2879 for (i = 3;i < width * height * 4;i += 4)
2881 if (skindata[i] < 255)
2883 skinframe->hasalpha = true;
2887 if (r_loadfog && skinframe->hasalpha)
2889 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2890 memcpy(fogpixels, skindata, width * height * 4);
2891 for (i = 0;i < width * height * 4;i += 4)
2892 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2893 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2894 Mem_Free(fogpixels);
2898 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2899 //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]);
2904 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2908 skinframe_t *skinframe;
2910 if (cls.state == ca_dedicated)
2913 // if already loaded just return it, otherwise make a new skinframe
2914 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2915 if (skinframe && skinframe->base)
2918 skinframe->stain = NULL;
2919 skinframe->merged = NULL;
2920 skinframe->base = r_texture_notexture;
2921 skinframe->pants = NULL;
2922 skinframe->shirt = NULL;
2923 skinframe->nmap = r_texture_blanknormalmap;
2924 skinframe->gloss = NULL;
2925 skinframe->glow = NULL;
2926 skinframe->fog = NULL;
2927 skinframe->hasalpha = false;
2929 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2933 if (developer_loading.integer)
2934 Con_Printf("loading quake skin \"%s\"\n", name);
2936 // 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)
2937 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
2938 memcpy(skinframe->qpixels, skindata, width*height);
2939 skinframe->qwidth = width;
2940 skinframe->qheight = height;
2943 for (i = 0;i < width * height;i++)
2944 featuresmask |= palette_featureflags[skindata[i]];
2946 skinframe->hasalpha = false;
2947 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
2948 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
2949 skinframe->qgeneratemerged = true;
2950 skinframe->qgeneratebase = skinframe->qhascolormapping;
2951 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
2953 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
2954 //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]);
2959 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
2963 unsigned char *skindata;
2965 if (!skinframe->qpixels)
2968 if (!skinframe->qhascolormapping)
2969 colormapped = false;
2973 if (!skinframe->qgeneratebase)
2978 if (!skinframe->qgeneratemerged)
2982 width = skinframe->qwidth;
2983 height = skinframe->qheight;
2984 skindata = skinframe->qpixels;
2986 if (skinframe->qgeneratenmap)
2988 unsigned char *temp1, *temp2;
2989 skinframe->qgeneratenmap = false;
2990 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2991 temp2 = temp1 + width * height * 4;
2992 // use either a custom palette or the quake palette
2993 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2994 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2995 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2999 if (skinframe->qgenerateglow)
3001 skinframe->qgenerateglow = false;
3002 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
3007 skinframe->qgeneratebase = false;
3008 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);
3009 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
3010 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
3014 skinframe->qgeneratemerged = false;
3015 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3018 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3020 Mem_Free(skinframe->qpixels);
3021 skinframe->qpixels = NULL;
3025 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)
3028 skinframe_t *skinframe;
3030 if (cls.state == ca_dedicated)
3033 // if already loaded just return it, otherwise make a new skinframe
3034 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3035 if (skinframe && skinframe->base)
3038 skinframe->stain = NULL;
3039 skinframe->merged = NULL;
3040 skinframe->base = r_texture_notexture;
3041 skinframe->pants = NULL;
3042 skinframe->shirt = NULL;
3043 skinframe->nmap = r_texture_blanknormalmap;
3044 skinframe->gloss = NULL;
3045 skinframe->glow = NULL;
3046 skinframe->fog = NULL;
3047 skinframe->hasalpha = false;
3049 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3053 if (developer_loading.integer)
3054 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3056 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3057 if (textureflags & TEXF_ALPHA)
3059 for (i = 0;i < width * height;i++)
3061 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3063 skinframe->hasalpha = true;
3067 if (r_loadfog && skinframe->hasalpha)
3068 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3071 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3072 //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]);
3077 skinframe_t *R_SkinFrame_LoadMissing(void)
3079 skinframe_t *skinframe;
3081 if (cls.state == ca_dedicated)
3084 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
3085 skinframe->stain = NULL;
3086 skinframe->merged = NULL;
3087 skinframe->base = r_texture_notexture;
3088 skinframe->pants = NULL;
3089 skinframe->shirt = NULL;
3090 skinframe->nmap = r_texture_blanknormalmap;
3091 skinframe->gloss = NULL;
3092 skinframe->glow = NULL;
3093 skinframe->fog = NULL;
3094 skinframe->hasalpha = false;
3096 skinframe->avgcolor[0] = rand() / RAND_MAX;
3097 skinframe->avgcolor[1] = rand() / RAND_MAX;
3098 skinframe->avgcolor[2] = rand() / RAND_MAX;
3099 skinframe->avgcolor[3] = 1;
3104 void R_Main_FreeViewCache(void)
3106 if (r_refdef.viewcache.entityvisible)
3107 Mem_Free(r_refdef.viewcache.entityvisible);
3108 if (r_refdef.viewcache.world_pvsbits)
3109 Mem_Free(r_refdef.viewcache.world_pvsbits);
3110 if (r_refdef.viewcache.world_leafvisible)
3111 Mem_Free(r_refdef.viewcache.world_leafvisible);
3112 if (r_refdef.viewcache.world_surfacevisible)
3113 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3114 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3117 void R_Main_ResizeViewCache(void)
3119 int numentities = r_refdef.scene.numentities;
3120 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3121 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3122 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3123 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3124 if (r_refdef.viewcache.maxentities < numentities)
3126 r_refdef.viewcache.maxentities = numentities;
3127 if (r_refdef.viewcache.entityvisible)
3128 Mem_Free(r_refdef.viewcache.entityvisible);
3129 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3131 if (r_refdef.viewcache.world_numclusters != numclusters)
3133 r_refdef.viewcache.world_numclusters = numclusters;
3134 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3135 if (r_refdef.viewcache.world_pvsbits)
3136 Mem_Free(r_refdef.viewcache.world_pvsbits);
3137 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3139 if (r_refdef.viewcache.world_numleafs != numleafs)
3141 r_refdef.viewcache.world_numleafs = numleafs;
3142 if (r_refdef.viewcache.world_leafvisible)
3143 Mem_Free(r_refdef.viewcache.world_leafvisible);
3144 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3146 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3148 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3149 if (r_refdef.viewcache.world_surfacevisible)
3150 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3151 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3155 extern rtexture_t *loadingscreentexture;
3156 void gl_main_start(void)
3158 loadingscreentexture = NULL;
3159 r_texture_blanknormalmap = NULL;
3160 r_texture_white = NULL;
3161 r_texture_grey128 = NULL;
3162 r_texture_black = NULL;
3163 r_texture_whitecube = NULL;
3164 r_texture_normalizationcube = NULL;
3165 r_texture_fogattenuation = NULL;
3166 r_texture_gammaramps = NULL;
3168 switch(vid.renderpath)
3170 case RENDERPATH_GL20:
3171 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3172 Cvar_SetValueQuick(&gl_combine, 1);
3173 Cvar_SetValueQuick(&r_glsl, 1);
3174 r_loadnormalmap = true;
3178 case RENDERPATH_GL13:
3179 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3180 Cvar_SetValueQuick(&gl_combine, 1);
3181 Cvar_SetValueQuick(&r_glsl, 0);
3182 r_loadnormalmap = false;
3183 r_loadgloss = false;
3186 case RENDERPATH_GL11:
3187 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3188 Cvar_SetValueQuick(&gl_combine, 0);
3189 Cvar_SetValueQuick(&r_glsl, 0);
3190 r_loadnormalmap = false;
3191 r_loadgloss = false;
3197 R_FrameData_Reset();
3201 memset(r_queries, 0, sizeof(r_queries));
3203 r_qwskincache = NULL;
3204 r_qwskincache_size = 0;
3206 // set up r_skinframe loading system for textures
3207 memset(&r_skinframe, 0, sizeof(r_skinframe));
3208 r_skinframe.loadsequence = 1;
3209 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3211 r_main_texturepool = R_AllocTexturePool();
3212 R_BuildBlankTextures();
3214 if (vid.support.arb_texture_cube_map)
3217 R_BuildNormalizationCube();
3219 r_texture_fogattenuation = NULL;
3220 r_texture_gammaramps = NULL;
3221 //r_texture_fogintensity = NULL;
3222 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3223 memset(&r_waterstate, 0, sizeof(r_waterstate));
3224 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3225 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3226 memset(&r_svbsp, 0, sizeof (r_svbsp));
3228 r_refdef.fogmasktable_density = 0;
3231 void gl_main_shutdown(void)
3234 R_FrameData_Reset();
3236 R_Main_FreeViewCache();
3239 qglDeleteQueriesARB(r_maxqueries, r_queries);
3243 memset(r_queries, 0, sizeof(r_queries));
3245 r_qwskincache = NULL;
3246 r_qwskincache_size = 0;
3248 // clear out the r_skinframe state
3249 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3250 memset(&r_skinframe, 0, sizeof(r_skinframe));
3253 Mem_Free(r_svbsp.nodes);
3254 memset(&r_svbsp, 0, sizeof (r_svbsp));
3255 R_FreeTexturePool(&r_main_texturepool);
3256 loadingscreentexture = NULL;
3257 r_texture_blanknormalmap = NULL;
3258 r_texture_white = NULL;
3259 r_texture_grey128 = NULL;
3260 r_texture_black = NULL;
3261 r_texture_whitecube = NULL;
3262 r_texture_normalizationcube = NULL;
3263 r_texture_fogattenuation = NULL;
3264 r_texture_gammaramps = NULL;
3265 //r_texture_fogintensity = NULL;
3266 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3267 memset(&r_waterstate, 0, sizeof(r_waterstate));
3271 extern void CL_ParseEntityLump(char *entitystring);
3272 void gl_main_newmap(void)
3274 // FIXME: move this code to client
3276 char *entities, entname[MAX_QPATH];
3278 Mem_Free(r_qwskincache);
3279 r_qwskincache = NULL;
3280 r_qwskincache_size = 0;
3283 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
3284 l = (int)strlen(entname) - 4;
3285 if (l >= 0 && !strcmp(entname + l, ".bsp"))
3287 memcpy(entname + l, ".ent", 5);
3288 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3290 CL_ParseEntityLump(entities);
3295 if (cl.worldmodel->brush.entities)
3296 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3298 R_Main_FreeViewCache();
3300 R_FrameData_Reset();
3303 void GL_Main_Init(void)
3305 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3307 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3308 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3309 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3310 if (gamemode == GAME_NEHAHRA)
3312 Cvar_RegisterVariable (&gl_fogenable);
3313 Cvar_RegisterVariable (&gl_fogdensity);
3314 Cvar_RegisterVariable (&gl_fogred);
3315 Cvar_RegisterVariable (&gl_foggreen);
3316 Cvar_RegisterVariable (&gl_fogblue);
3317 Cvar_RegisterVariable (&gl_fogstart);
3318 Cvar_RegisterVariable (&gl_fogend);
3319 Cvar_RegisterVariable (&gl_skyclip);
3321 Cvar_RegisterVariable(&r_motionblur);
3322 Cvar_RegisterVariable(&r_motionblur_maxblur);
3323 Cvar_RegisterVariable(&r_motionblur_bmin);
3324 Cvar_RegisterVariable(&r_motionblur_vmin);
3325 Cvar_RegisterVariable(&r_motionblur_vmax);
3326 Cvar_RegisterVariable(&r_motionblur_vcoeff);
3327 Cvar_RegisterVariable(&r_motionblur_randomize);
3328 Cvar_RegisterVariable(&r_damageblur);
3329 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3330 Cvar_RegisterVariable(&r_equalize_entities_minambient);
3331 Cvar_RegisterVariable(&r_equalize_entities_by);
3332 Cvar_RegisterVariable(&r_equalize_entities_to);
3333 Cvar_RegisterVariable(&r_depthfirst);
3334 Cvar_RegisterVariable(&r_useinfinitefarclip);
3335 Cvar_RegisterVariable(&r_farclip_base);
3336 Cvar_RegisterVariable(&r_farclip_world);
3337 Cvar_RegisterVariable(&r_nearclip);
3338 Cvar_RegisterVariable(&r_showbboxes);
3339 Cvar_RegisterVariable(&r_showsurfaces);
3340 Cvar_RegisterVariable(&r_showtris);
3341 Cvar_RegisterVariable(&r_shownormals);
3342 Cvar_RegisterVariable(&r_showlighting);
3343 Cvar_RegisterVariable(&r_showshadowvolumes);
3344 Cvar_RegisterVariable(&r_showcollisionbrushes);
3345 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3346 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3347 Cvar_RegisterVariable(&r_showdisabledepthtest);
3348 Cvar_RegisterVariable(&r_drawportals);
3349 Cvar_RegisterVariable(&r_drawentities);
3350 Cvar_RegisterVariable(&r_cullentities_trace);
3351 Cvar_RegisterVariable(&r_cullentities_trace_samples);
3352 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
3353 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3354 Cvar_RegisterVariable(&r_cullentities_trace_delay);
3355 Cvar_RegisterVariable(&r_drawviewmodel);
3356 Cvar_RegisterVariable(&r_speeds);
3357 Cvar_RegisterVariable(&r_fullbrights);
3358 Cvar_RegisterVariable(&r_wateralpha);
3359 Cvar_RegisterVariable(&r_dynamic);
3360 Cvar_RegisterVariable(&r_fullbright);
3361 Cvar_RegisterVariable(&r_shadows);
3362 Cvar_RegisterVariable(&r_shadows_darken);
3363 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3364 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3365 Cvar_RegisterVariable(&r_shadows_throwdistance);
3366 Cvar_RegisterVariable(&r_shadows_throwdirection);
3367 Cvar_RegisterVariable(&r_q1bsp_skymasking);
3368 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3369 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3370 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3371 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3372 Cvar_RegisterVariable(&r_fog_exp2);
3373 Cvar_RegisterVariable(&r_drawfog);
3374 Cvar_RegisterVariable(&r_transparentdepthmasking);
3375 Cvar_RegisterVariable(&r_textureunits);
3376 Cvar_RegisterVariable(&gl_combine);
3377 Cvar_RegisterVariable(&r_glsl);
3378 Cvar_RegisterVariable(&r_glsl_deluxemapping);
3379 Cvar_RegisterVariable(&r_glsl_offsetmapping);
3380 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3381 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3382 Cvar_RegisterVariable(&r_glsl_postprocess);
3383 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3384 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3385 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3386 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3387 Cvar_RegisterVariable(&r_water);
3388 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3389 Cvar_RegisterVariable(&r_water_clippingplanebias);
3390 Cvar_RegisterVariable(&r_water_refractdistort);
3391 Cvar_RegisterVariable(&r_water_reflectdistort);
3392 Cvar_RegisterVariable(&r_lerpsprites);
3393 Cvar_RegisterVariable(&r_lerpmodels);
3394 Cvar_RegisterVariable(&r_lerplightstyles);
3395 Cvar_RegisterVariable(&r_waterscroll);
3396 Cvar_RegisterVariable(&r_bloom);
3397 Cvar_RegisterVariable(&r_bloom_colorscale);
3398 Cvar_RegisterVariable(&r_bloom_brighten);
3399 Cvar_RegisterVariable(&r_bloom_blur);
3400 Cvar_RegisterVariable(&r_bloom_resolution);
3401 Cvar_RegisterVariable(&r_bloom_colorexponent);
3402 Cvar_RegisterVariable(&r_bloom_colorsubtract);
3403 Cvar_RegisterVariable(&r_hdr);
3404 Cvar_RegisterVariable(&r_hdr_scenebrightness);
3405 Cvar_RegisterVariable(&r_hdr_glowintensity);
3406 Cvar_RegisterVariable(&r_hdr_range);
3407 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3408 Cvar_RegisterVariable(&developer_texturelogging);
3409 Cvar_RegisterVariable(&gl_lightmaps);
3410 Cvar_RegisterVariable(&r_test);
3411 Cvar_RegisterVariable(&r_batchmode);
3412 Cvar_RegisterVariable(&r_glsl_saturation);
3413 Cvar_RegisterVariable(&r_framedatasize);
3414 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3415 Cvar_SetValue("r_fullbrights", 0);
3416 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3418 Cvar_RegisterVariable(&r_track_sprites);
3419 Cvar_RegisterVariable(&r_track_sprites_flags);
3420 Cvar_RegisterVariable(&r_track_sprites_scalew);
3421 Cvar_RegisterVariable(&r_track_sprites_scaleh);
3424 extern void R_Textures_Init(void);
3425 extern void GL_Draw_Init(void);
3426 extern void GL_Main_Init(void);
3427 extern void R_Shadow_Init(void);
3428 extern void R_Sky_Init(void);
3429 extern void GL_Surf_Init(void);
3430 extern void R_Particles_Init(void);
3431 extern void R_Explosion_Init(void);
3432 extern void gl_backend_init(void);
3433 extern void Sbar_Init(void);
3434 extern void R_LightningBeams_Init(void);
3435 extern void Mod_RenderInit(void);
3437 void Render_Init(void)
3449 R_LightningBeams_Init();
3458 extern char *ENGINE_EXTENSIONS;
3461 gl_renderer = (const char *)qglGetString(GL_RENDERER);
3462 gl_vendor = (const char *)qglGetString(GL_VENDOR);
3463 gl_version = (const char *)qglGetString(GL_VERSION);
3464 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3468 if (!gl_platformextensions)
3469 gl_platformextensions = "";
3471 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3472 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3473 Con_Printf("GL_VERSION: %s\n", gl_version);
3474 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3475 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3477 VID_CheckExtensions();
3479 // LordHavoc: report supported extensions
3480 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3482 // clear to black (loading plaque will be seen over this)
3484 qglClearColor(0,0,0,1);CHECKGLERROR
3485 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3488 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3492 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3494 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3497 p = r_refdef.view.frustum + i;
3502 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3506 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3510 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3514 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3518 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3522 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3526 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3530 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3538 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3542 for (i = 0;i < numplanes;i++)
3549 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3553 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3557 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3561 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3565 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3569 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3573 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3577 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3585 //==================================================================================
3587 // LordHavoc: this stores temporary data used within the same frame
3589 qboolean r_framedata_failed;
3590 static size_t r_framedata_size;
3591 static size_t r_framedata_current;
3592 static void *r_framedata_base;
3594 void R_FrameData_Reset(void)
3596 if (r_framedata_base);
3597 Mem_Free(r_framedata_base);
3598 r_framedata_base = NULL;
3599 r_framedata_size = 0;
3600 r_framedata_current = 0;
3601 r_framedata_failed = false;
3604 void R_FrameData_NewFrame(void)
3607 if (r_framedata_failed)
3608 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
3609 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
3610 wantedsize = bound(65536, wantedsize, 128*1024*1024);
3611 if (r_framedata_size != wantedsize)
3613 r_framedata_size = wantedsize;
3614 if (r_framedata_base);
3615 Mem_Free(r_framedata_base);
3616 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
3618 r_framedata_current = 0;
3619 r_framedata_failed = false;
3622 void *R_FrameData_Alloc(size_t size)
3626 // align to 16 byte boundary
3627 size = (size + 15) & ~15;
3628 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
3629 r_framedata_current += size;
3632 if (r_framedata_current > r_framedata_size)
3633 r_framedata_failed = true;
3635 // return NULL on everything after a failure
3636 if (r_framedata_failed)
3642 void *R_FrameData_Store(size_t size, void *data)
3644 void *d = R_FrameData_Alloc(size);
3646 memcpy(d, data, size);
3650 //==================================================================================
3652 // LordHavoc: animcache originally written by Echon, rewritten since then
3655 * Animation cache prevents re-generating mesh data for an animated model
3656 * multiple times in one frame for lighting, shadowing, reflections, etc.
3659 void R_AnimCache_Free(void)
3663 void R_AnimCache_ClearCache(void)
3666 entity_render_t *ent;
3668 for (i = 0;i < r_refdef.scene.numentities;i++)
3670 ent = r_refdef.scene.entities[i];
3671 ent->animcache_vertex3f = NULL;
3672 ent->animcache_normal3f = NULL;
3673 ent->animcache_svector3f = NULL;
3674 ent->animcache_tvector3f = NULL;
3678 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3680 dp_model_t *model = ent->model;
3682 // see if it's already cached this frame
3683 if (ent->animcache_vertex3f)
3685 // add normals/tangents if needed
3686 if (wantnormals || wanttangents)
3688 if (ent->animcache_normal3f)
3689 wantnormals = false;
3690 if (ent->animcache_svector3f)
3691 wanttangents = false;
3692 if (wantnormals || wanttangents)
3694 numvertices = model->surfmesh.num_vertices;
3696 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3699 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3700 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3702 if (!r_framedata_failed)
3703 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
3709 // see if this ent is worth caching
3710 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
3712 // get some memory for this entity and generate mesh data
3713 numvertices = model->surfmesh.num_vertices;
3714 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3716 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3719 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3720 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
3722 if (!r_framedata_failed)
3723 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
3725 return !r_framedata_failed;
3728 void R_AnimCache_CacheVisibleEntities(void)
3731 qboolean wantnormals = !r_showsurfaces.integer;
3732 qboolean wanttangents = !r_showsurfaces.integer;
3734 switch(vid.renderpath)
3736 case RENDERPATH_GL20:
3738 case RENDERPATH_GL13:
3739 case RENDERPATH_GL11:
3740 wanttangents = false;
3744 // TODO: thread this
3745 // NOTE: R_PrepareRTLights() also caches entities
3747 for (i = 0;i < r_refdef.scene.numentities;i++)
3748 if (r_refdef.viewcache.entityvisible[i])
3749 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3751 if (r_shadows.integer)
3752 for (i = 0;i < r_refdef.scene.numentities;i++)
3753 if (!r_refdef.viewcache.entityvisible[i])
3754 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
3757 //==================================================================================
3759 static void R_View_UpdateEntityLighting (void)
3762 entity_render_t *ent;
3763 vec3_t tempdiffusenormal, avg;
3764 vec_t f, fa, fd, fdd;
3766 for (i = 0;i < r_refdef.scene.numentities;i++)
3768 ent = r_refdef.scene.entities[i];
3770 // skip unseen models
3771 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3775 if (ent->model && ent->model->brush.num_leafs)
3777 // TODO: use modellight for r_ambient settings on world?
3778 VectorSet(ent->modellight_ambient, 0, 0, 0);
3779 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3780 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3784 // fetch the lighting from the worldmodel data
3785 VectorClear(ent->modellight_ambient);
3786 VectorClear(ent->modellight_diffuse);
3787 VectorClear(tempdiffusenormal);
3788 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3791 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3792 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3793 if(ent->flags & RENDER_EQUALIZE)
3795 // first fix up ambient lighting...
3796 if(r_equalize_entities_minambient.value > 0)
3798 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3801 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3802 if(fa < r_equalize_entities_minambient.value * fd)
3805 // fa'/fd' = minambient
3806 // fa'+0.25*fd' = fa+0.25*fd
3808 // fa' = fd' * minambient
3809 // fd'*(0.25+minambient) = fa+0.25*fd
3811 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3812 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3814 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3815 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
3816 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3817 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3822 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3824 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3825 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3828 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3829 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3830 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3836 VectorSet(ent->modellight_ambient, 1, 1, 1);
3838 // move the light direction into modelspace coordinates for lighting code
3839 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3840 if(VectorLength2(ent->modellight_lightdir) == 0)
3841 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3842 VectorNormalize(ent->modellight_lightdir);
3846 #define MAX_LINEOFSIGHTTRACES 64
3848 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3851 vec3_t boxmins, boxmaxs;
3854 dp_model_t *model = r_refdef.scene.worldmodel;
3856 if (!model || !model->brush.TraceLineOfSight)
3859 // expand the box a little
3860 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3861 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3862 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3863 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3864 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3865 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3868 VectorCopy(eye, start);
3869 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3870 if (model->brush.TraceLineOfSight(model, start, end))
3873 // try various random positions
3874 for (i = 0;i < numsamples;i++)
3876 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3877 if (model->brush.TraceLineOfSight(model, start, end))
3885 static void R_View_UpdateEntityVisible (void)
3890 entity_render_t *ent;
3892 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3893 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3895 // worldmodel can check visibility
3896 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3897 for (i = 0;i < r_refdef.scene.numentities;i++)
3899 ent = r_refdef.scene.entities[i];
3900 if (!(ent->flags & renderimask))
3901 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)))
3902 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))
3903 r_refdef.viewcache.entityvisible[i] = true;
3905 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3907 for (i = 0;i < r_refdef.scene.numentities;i++)
3909 ent = r_refdef.scene.entities[i];
3910 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3912 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
3914 continue; // temp entities do pvs only
3915 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3916 ent->last_trace_visibility = realtime;
3917 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3918 r_refdef.viewcache.entityvisible[i] = 0;
3925 // no worldmodel or it can't check visibility
3926 for (i = 0;i < r_refdef.scene.numentities;i++)
3928 ent = r_refdef.scene.entities[i];
3929 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));
3934 /// only used if skyrendermasked, and normally returns false
3935 int R_DrawBrushModelsSky (void)
3938 entity_render_t *ent;
3941 for (i = 0;i < r_refdef.scene.numentities;i++)
3943 if (!r_refdef.viewcache.entityvisible[i])
3945 ent = r_refdef.scene.entities[i];
3946 if (!ent->model || !ent->model->DrawSky)
3948 ent->model->DrawSky(ent);
3954 static void R_DrawNoModel(entity_render_t *ent);
3955 static void R_DrawModels(void)
3958 entity_render_t *ent;
3960 for (i = 0;i < r_refdef.scene.numentities;i++)
3962 if (!r_refdef.viewcache.entityvisible[i])
3964 ent = r_refdef.scene.entities[i];
3965 r_refdef.stats.entities++;
3966 if (ent->model && ent->model->Draw != NULL)
3967 ent->model->Draw(ent);
3973 static void R_DrawModelsDepth(void)
3976 entity_render_t *ent;
3978 for (i = 0;i < r_refdef.scene.numentities;i++)
3980 if (!r_refdef.viewcache.entityvisible[i])
3982 ent = r_refdef.scene.entities[i];
3983 if (ent->model && ent->model->DrawDepth != NULL)
3984 ent->model->DrawDepth(ent);
3988 static void R_DrawModelsDebug(void)
3991 entity_render_t *ent;
3993 for (i = 0;i < r_refdef.scene.numentities;i++)
3995 if (!r_refdef.viewcache.entityvisible[i])
3997 ent = r_refdef.scene.entities[i];
3998 if (ent->model && ent->model->DrawDebug != NULL)
3999 ent->model->DrawDebug(ent);
4003 static void R_DrawModelsAddWaterPlanes(void)
4006 entity_render_t *ent;
4008 for (i = 0;i < r_refdef.scene.numentities;i++)
4010 if (!r_refdef.viewcache.entityvisible[i])
4012 ent = r_refdef.scene.entities[i];
4013 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4014 ent->model->DrawAddWaterPlanes(ent);
4018 static void R_View_SetFrustum(void)
4021 double slopex, slopey;
4022 vec3_t forward, left, up, origin;
4024 // we can't trust r_refdef.view.forward and friends in reflected scenes
4025 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4028 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4029 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4030 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4031 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4032 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4033 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4034 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4035 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4036 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4037 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4038 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4039 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4043 zNear = r_refdef.nearclip;
4044 nudge = 1.0 - 1.0 / (1<<23);
4045 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4046 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4047 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4048 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4049 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4050 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4051 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4052 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4058 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4059 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4060 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4061 r_refdef.view.frustum[0].dist = m[15] - m[12];
4063 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4064 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4065 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4066 r_refdef.view.frustum[1].dist = m[15] + m[12];
4068 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4069 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4070 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4071 r_refdef.view.frustum[2].dist = m[15] - m[13];
4073 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4074 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4075 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4076 r_refdef.view.frustum[3].dist = m[15] + m[13];
4078 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4079 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4080 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4081 r_refdef.view.frustum[4].dist = m[15] - m[14];
4083 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4084 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4085 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4086 r_refdef.view.frustum[5].dist = m[15] + m[14];
4089 if (r_refdef.view.useperspective)
4091 slopex = 1.0 / r_refdef.view.frustum_x;
4092 slopey = 1.0 / r_refdef.view.frustum_y;
4093 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4094 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
4095 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
4096 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
4097 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4099 // Leaving those out was a mistake, those were in the old code, and they
4100 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4101 // I couldn't reproduce it after adding those normalizations. --blub
4102 VectorNormalize(r_refdef.view.frustum[0].normal);
4103 VectorNormalize(r_refdef.view.frustum[1].normal);
4104 VectorNormalize(r_refdef.view.frustum[2].normal);
4105 VectorNormalize(r_refdef.view.frustum[3].normal);
4107 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4108 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]);
4109 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]);
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[2]);
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[3]);
4113 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4114 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4115 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4116 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4117 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4121 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4122 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4123 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4124 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4125 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4126 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4127 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4128 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4129 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4130 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4132 r_refdef.view.numfrustumplanes = 5;
4134 if (r_refdef.view.useclipplane)
4136 r_refdef.view.numfrustumplanes = 6;
4137 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4140 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4141 PlaneClassify(r_refdef.view.frustum + i);
4143 // LordHavoc: note to all quake engine coders, Quake had a special case
4144 // for 90 degrees which assumed a square view (wrong), so I removed it,
4145 // Quake2 has it disabled as well.
4147 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4148 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4149 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4150 //PlaneClassify(&frustum[0]);
4152 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4153 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4154 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4155 //PlaneClassify(&frustum[1]);
4157 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4158 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4159 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4160 //PlaneClassify(&frustum[2]);
4162 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4163 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4164 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4165 //PlaneClassify(&frustum[3]);
4168 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4169 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4170 //PlaneClassify(&frustum[4]);
4173 void R_View_Update(void)
4175 R_Main_ResizeViewCache();
4176 R_View_SetFrustum();
4177 R_View_WorldVisibility(r_refdef.view.useclipplane);
4178 R_View_UpdateEntityVisible();
4179 R_View_UpdateEntityLighting();
4182 void R_SetupView(qboolean allowwaterclippingplane)
4184 const double *customclipplane = NULL;
4186 if (r_refdef.view.useclipplane && allowwaterclippingplane)
4188 // LordHavoc: couldn't figure out how to make this approach the
4189 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4190 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4191 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4192 dist = r_refdef.view.clipplane.dist;
4193 plane[0] = r_refdef.view.clipplane.normal[0];
4194 plane[1] = r_refdef.view.clipplane.normal[1];
4195 plane[2] = r_refdef.view.clipplane.normal[2];
4197 customclipplane = plane;
4200 if (!r_refdef.view.useperspective)
4201 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);
4202 else if (vid.stencil && r_useinfinitefarclip.integer)
4203 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);
4205 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);
4206 R_SetViewport(&r_refdef.view.viewport);
4209 void R_ResetViewRendering2D(void)
4211 r_viewport_t viewport;
4214 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
4215 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);
4216 R_SetViewport(&viewport);
4217 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
4218 GL_Color(1, 1, 1, 1);
4219 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4220 GL_BlendFunc(GL_ONE, GL_ZERO);
4221 GL_AlphaTest(false);
4222 GL_ScissorTest(false);
4223 GL_DepthMask(false);
4224 GL_DepthRange(0, 1);
4225 GL_DepthTest(false);
4226 R_Mesh_Matrix(&identitymatrix);
4227 R_Mesh_ResetTextureState();
4228 GL_PolygonOffset(0, 0);
4229 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4230 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4231 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4232 qglStencilMask(~0);CHECKGLERROR
4233 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4234 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4235 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
4236 R_SetupGenericShader(true);
4239 void R_ResetViewRendering3D(void)
4244 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
4245 GL_Color(1, 1, 1, 1);
4246 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
4247 GL_BlendFunc(GL_ONE, GL_ZERO);
4248 GL_AlphaTest(false);
4249 GL_ScissorTest(true);
4251 GL_DepthRange(0, 1);
4253 R_Mesh_Matrix(&identitymatrix);
4254 R_Mesh_ResetTextureState();
4255 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4256 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
4257 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
4258 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
4259 qglStencilMask(~0);CHECKGLERROR
4260 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
4261 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
4262 GL_CullFace(r_refdef.view.cullface_back);
4263 R_SetupGenericShader(true);
4266 void R_RenderScene(void);
4267 void R_RenderWaterPlanes(void);
4269 static void R_Water_StartFrame(void)
4272 int waterwidth, waterheight, texturewidth, textureheight;
4273 r_waterstate_waterplane_t *p;
4275 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
4278 switch(vid.renderpath)
4280 case RENDERPATH_GL20:
4282 case RENDERPATH_GL13:
4283 case RENDERPATH_GL11:
4287 // set waterwidth and waterheight to the water resolution that will be
4288 // used (often less than the screen resolution for faster rendering)
4289 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
4290 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
4292 // calculate desired texture sizes
4293 // can't use water if the card does not support the texture size
4294 if (!r_water.integer || r_showsurfaces.integer)
4295 texturewidth = textureheight = waterwidth = waterheight = 0;
4296 else if (vid.support.arb_texture_non_power_of_two)
4298 texturewidth = waterwidth;
4299 textureheight = waterheight;
4303 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
4304 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
4307 // allocate textures as needed
4308 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4310 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4311 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4313 if (p->texture_refraction)
4314 R_FreeTexture(p->texture_refraction);
4315 p->texture_refraction = NULL;
4316 if (p->texture_reflection)
4317 R_FreeTexture(p->texture_reflection);
4318 p->texture_reflection = NULL;
4320 memset(&r_waterstate, 0, sizeof(r_waterstate));
4321 r_waterstate.texturewidth = texturewidth;
4322 r_waterstate.textureheight = textureheight;
4325 if (r_waterstate.texturewidth)
4327 r_waterstate.enabled = true;
4329 // when doing a reduced render (HDR) we want to use a smaller area
4330 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4331 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4333 // set up variables that will be used in shader setup
4334 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4335 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4336 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4337 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4340 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4341 r_waterstate.numwaterplanes = 0;
4344 void R_Water_AddWaterPlane(msurface_t *surface)
4346 int triangleindex, planeindex;
4352 r_waterstate_waterplane_t *p;
4353 texture_t *t = R_GetCurrentTexture(surface->texture);
4354 // just use the first triangle with a valid normal for any decisions
4355 VectorClear(normal);
4356 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4358 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4359 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4360 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4361 TriangleNormal(vert[0], vert[1], vert[2], normal);
4362 if (VectorLength2(normal) >= 0.001)
4366 VectorCopy(normal, plane.normal);
4367 VectorNormalize(plane.normal);
4368 plane.dist = DotProduct(vert[0], plane.normal);
4369 PlaneClassify(&plane);
4370 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4372 // skip backfaces (except if nocullface is set)
4373 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4375 VectorNegate(plane.normal, plane.normal);
4377 PlaneClassify(&plane);
4381 // find a matching plane if there is one
4382 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4383 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4385 if (planeindex >= r_waterstate.maxwaterplanes)
4386 return; // nothing we can do, out of planes
4388 // if this triangle does not fit any known plane rendered this frame, add one
4389 if (planeindex >= r_waterstate.numwaterplanes)
4391 // store the new plane
4392 r_waterstate.numwaterplanes++;
4394 // clear materialflags and pvs
4395 p->materialflags = 0;
4396 p->pvsvalid = false;
4398 // merge this surface's materialflags into the waterplane
4399 p->materialflags |= t->currentmaterialflags;
4400 // merge this surface's PVS into the waterplane
4401 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4402 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4403 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4405 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4410 static void R_Water_ProcessPlanes(void)
4412 r_refdef_view_t originalview;
4413 r_refdef_view_t myview;
4415 r_waterstate_waterplane_t *p;
4417 originalview = r_refdef.view;
4419 // make sure enough textures are allocated
4420 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4422 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4424 if (!p->texture_refraction)
4425 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
4426 if (!p->texture_refraction)
4430 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4432 if (!p->texture_reflection)
4433 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
4434 if (!p->texture_reflection)
4440 r_refdef.view = originalview;
4441 r_refdef.view.showdebug = false;
4442 r_refdef.view.width = r_waterstate.waterwidth;
4443 r_refdef.view.height = r_waterstate.waterheight;
4444 r_refdef.view.useclipplane = true;
4445 myview = r_refdef.view;
4446 r_waterstate.renderingscene = true;
4447 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4449 // render the normal view scene and copy into texture
4450 // (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)
4451 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4453 r_refdef.view = myview;
4454 r_refdef.view.clipplane = p->plane;
4455 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4456 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4457 PlaneClassify(&r_refdef.view.clipplane);
4459 R_ResetViewRendering3D();
4460 R_ClearScreen(r_refdef.fogenabled);
4464 // copy view into the screen texture
4465 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4466 GL_ActiveTexture(0);
4468 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
4471 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4473 r_refdef.view = myview;
4474 // render reflected scene and copy into texture
4475 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4476 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4477 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4478 r_refdef.view.clipplane = p->plane;
4479 // reverse the cullface settings for this render
4480 r_refdef.view.cullface_front = GL_FRONT;
4481 r_refdef.view.cullface_back = GL_BACK;
4482 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4484 r_refdef.view.usecustompvs = true;
4486 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4488 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4491 R_ResetViewRendering3D();
4492 R_ClearScreen(r_refdef.fogenabled);
4496 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4497 GL_ActiveTexture(0);
4499 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
4502 r_waterstate.renderingscene = false;
4503 r_refdef.view = originalview;
4504 R_ResetViewRendering3D();
4505 R_ClearScreen(r_refdef.fogenabled);
4509 r_refdef.view = originalview;
4510 r_waterstate.renderingscene = false;
4511 Cvar_SetValueQuick(&r_water, 0);
4512 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
4516 void R_Bloom_StartFrame(void)
4518 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4520 switch(vid.renderpath)
4522 case RENDERPATH_GL20:
4524 case RENDERPATH_GL13:
4525 case RENDERPATH_GL11:
4529 // set bloomwidth and bloomheight to the bloom resolution that will be
4530 // used (often less than the screen resolution for faster rendering)
4531 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4532 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4533 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4534 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
4535 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
4537 // calculate desired texture sizes
4538 if (vid.support.arb_texture_non_power_of_two)
4540 screentexturewidth = r_refdef.view.width;
4541 screentextureheight = r_refdef.view.height;
4542 bloomtexturewidth = r_bloomstate.bloomwidth;
4543 bloomtextureheight = r_bloomstate.bloomheight;
4547 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
4548 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
4549 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
4550 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
4553 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))
4555 Cvar_SetValueQuick(&r_hdr, 0);
4556 Cvar_SetValueQuick(&r_bloom, 0);
4557 Cvar_SetValueQuick(&r_motionblur, 0);
4558 Cvar_SetValueQuick(&r_damageblur, 0);
4561 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)))
4562 screentexturewidth = screentextureheight = 0;
4563 if (!r_hdr.integer && !r_bloom.integer)
4564 bloomtexturewidth = bloomtextureheight = 0;
4566 // allocate textures as needed
4567 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4569 if (r_bloomstate.texture_screen)
4570 R_FreeTexture(r_bloomstate.texture_screen);
4571 r_bloomstate.texture_screen = NULL;
4572 r_bloomstate.screentexturewidth = screentexturewidth;
4573 r_bloomstate.screentextureheight = screentextureheight;
4574 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4575 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
4577 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4579 if (r_bloomstate.texture_bloom)
4580 R_FreeTexture(r_bloomstate.texture_bloom);
4581 r_bloomstate.texture_bloom = NULL;
4582 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4583 r_bloomstate.bloomtextureheight = bloomtextureheight;
4584 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4585 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
4588 // when doing a reduced render (HDR) we want to use a smaller area
4589 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4590 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4591 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4592 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4593 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4595 // set up a texcoord array for the full resolution screen image
4596 // (we have to keep this around to copy back during final render)
4597 r_bloomstate.screentexcoord2f[0] = 0;
4598 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4599 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4600 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4601 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4602 r_bloomstate.screentexcoord2f[5] = 0;
4603 r_bloomstate.screentexcoord2f[6] = 0;
4604 r_bloomstate.screentexcoord2f[7] = 0;
4606 // set up a texcoord array for the reduced resolution bloom image
4607 // (which will be additive blended over the screen image)
4608 r_bloomstate.bloomtexcoord2f[0] = 0;
4609 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4610 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4611 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4612 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4613 r_bloomstate.bloomtexcoord2f[5] = 0;
4614 r_bloomstate.bloomtexcoord2f[6] = 0;
4615 r_bloomstate.bloomtexcoord2f[7] = 0;
4617 if (r_hdr.integer || r_bloom.integer)
4619 r_bloomstate.enabled = true;
4620 r_bloomstate.hdr = r_hdr.integer != 0;
4623 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);
4626 void R_Bloom_CopyBloomTexture(float colorscale)
4628 r_refdef.stats.bloom++;
4630 // scale down screen texture to the bloom texture size
4632 R_SetViewport(&r_bloomstate.viewport);
4633 GL_BlendFunc(GL_ONE, GL_ZERO);
4634 GL_Color(colorscale, colorscale, colorscale, 1);
4635 // TODO: optimize with multitexture or GLSL
4636 R_SetupGenericShader(true);
4637 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4638 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4639 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4640 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4642 // we now have a bloom image in the framebuffer
4643 // copy it into the bloom image texture for later processing
4644 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4645 GL_ActiveTexture(0);
4647 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4648 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4651 void R_Bloom_CopyHDRTexture(void)
4653 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4654 GL_ActiveTexture(0);
4656 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
4657 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4660 void R_Bloom_MakeTexture(void)
4663 float xoffset, yoffset, r, brighten;
4665 r_refdef.stats.bloom++;
4667 R_ResetViewRendering2D();
4668 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4669 R_Mesh_ColorPointer(NULL, 0, 0);
4670 R_SetupGenericShader(true);
4672 // we have a bloom image in the framebuffer
4674 R_SetViewport(&r_bloomstate.viewport);
4676 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4679 r = bound(0, r_bloom_colorexponent.value / x, 1);
4680 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4681 GL_Color(r, r, r, 1);
4682 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4683 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4684 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4685 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4687 // copy the vertically blurred bloom view to a texture
4688 GL_ActiveTexture(0);
4690 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4691 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4694 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4695 brighten = r_bloom_brighten.value;
4697 brighten *= r_hdr_range.value;
4698 brighten = sqrt(brighten);
4700 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4701 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4702 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4704 for (dir = 0;dir < 2;dir++)
4706 // blend on at multiple vertical offsets to achieve a vertical blur
4707 // TODO: do offset blends using GLSL
4708 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4709 GL_BlendFunc(GL_ONE, GL_ZERO);
4710 for (x = -range;x <= range;x++)
4712 if (!dir){xoffset = 0;yoffset = x;}
4713 else {xoffset = x;yoffset = 0;}
4714 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4715 yoffset /= (float)r_bloomstate.bloomtextureheight;
4716 // compute a texcoord array with the specified x and y offset
4717 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4718 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4719 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4720 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4721 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4722 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4723 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4724 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4725 // this r value looks like a 'dot' particle, fading sharply to
4726 // black at the edges
4727 // (probably not realistic but looks good enough)
4728 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4729 //r = brighten/(range*2+1);
4730 r = brighten / (range * 2 + 1);
4732 r *= (1 - x*x/(float)(range*range));
4733 GL_Color(r, r, r, 1);
4734 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4735 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4736 GL_BlendFunc(GL_ONE, GL_ONE);
4739 // copy the vertically blurred bloom view to a texture
4740 GL_ActiveTexture(0);
4742 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4743 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4746 // apply subtract last
4747 // (just like it would be in a GLSL shader)
4748 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
4750 GL_BlendFunc(GL_ONE, GL_ZERO);
4751 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4752 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4753 GL_Color(1, 1, 1, 1);
4754 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4755 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4757 GL_BlendFunc(GL_ONE, GL_ONE);
4758 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4759 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4760 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4761 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4762 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4763 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4764 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4766 // copy the darkened bloom view to a texture
4767 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4768 GL_ActiveTexture(0);
4770 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4771 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4775 void R_HDR_RenderBloomTexture(void)
4777 int oldwidth, oldheight;
4778 float oldcolorscale;
4780 oldcolorscale = r_refdef.view.colorscale;
4781 oldwidth = r_refdef.view.width;
4782 oldheight = r_refdef.view.height;
4783 r_refdef.view.width = r_bloomstate.bloomwidth;
4784 r_refdef.view.height = r_bloomstate.bloomheight;
4786 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4787 // TODO: add exposure compensation features
4788 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4790 r_refdef.view.showdebug = false;
4791 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4793 R_ResetViewRendering3D();
4795 R_ClearScreen(r_refdef.fogenabled);
4796 if (r_timereport_active)
4797 R_TimeReport("HDRclear");
4800 if (r_timereport_active)
4801 R_TimeReport("visibility");
4803 // only do secondary renders with HDR if r_hdr is 2 or higher
4804 r_waterstate.numwaterplanes = 0;
4805 if (r_waterstate.enabled && r_hdr.integer >= 2)
4806 R_RenderWaterPlanes();
4808 r_refdef.view.showdebug = true;
4810 r_waterstate.numwaterplanes = 0;
4812 R_ResetViewRendering2D();
4814 R_Bloom_CopyHDRTexture();
4815 R_Bloom_MakeTexture();
4817 // restore the view settings
4818 r_refdef.view.width = oldwidth;
4819 r_refdef.view.height = oldheight;
4820 r_refdef.view.colorscale = oldcolorscale;
4822 R_ResetViewRendering3D();
4824 R_ClearScreen(r_refdef.fogenabled);
4825 if (r_timereport_active)
4826 R_TimeReport("viewclear");
4829 static void R_BlendView(void)
4831 unsigned int permutation;
4833 switch (vid.renderpath)
4835 case RENDERPATH_GL20:
4837 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4838 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4839 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4840 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4841 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4843 if (r_bloomstate.texture_screen)
4845 // make sure the buffer is available
4846 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4848 R_ResetViewRendering2D();
4849 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4850 R_Mesh_ColorPointer(NULL, 0, 0);
4851 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4852 GL_ActiveTexture(0);CHECKGLERROR
4854 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4856 // declare variables
4858 static float avgspeed;
4860 speed = VectorLength(cl.movement_velocity);
4862 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4863 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4865 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4866 speed = bound(0, speed, 1);
4867 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4869 // calculate values into a standard alpha
4870 cl.motionbluralpha = 1 - exp(-
4872 (r_motionblur.value * speed / 80)
4874 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4877 max(0.0001, cl.time - cl.oldtime) // fps independent
4880 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4881 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4883 if (cl.motionbluralpha > 0)
4885 R_SetupGenericShader(true);
4886 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4887 GL_Color(1, 1, 1, cl.motionbluralpha);
4888 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4889 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4890 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4891 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4895 // copy view into the screen texture
4896 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
4897 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4899 else if (!r_bloomstate.texture_bloom)
4901 // we may still have to do view tint...
4902 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4904 // apply a color tint to the whole view
4905 R_ResetViewRendering2D();
4906 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4907 R_Mesh_ColorPointer(NULL, 0, 0);
4908 R_SetupGenericShader(false);
4909 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4910 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4911 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4913 break; // no screen processing, no bloom, skip it
4916 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4918 // render simple bloom effect
4919 // copy the screen and shrink it and darken it for the bloom process
4920 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4921 // make the bloom texture
4922 R_Bloom_MakeTexture();
4925 R_ResetViewRendering2D();
4926 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4927 R_Mesh_ColorPointer(NULL, 0, 0);
4928 GL_Color(1, 1, 1, 1);
4929 GL_BlendFunc(GL_ONE, GL_ZERO);
4930 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4931 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4932 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4933 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4934 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4935 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4936 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4937 if (r_glsl_permutation->loc_ViewTintColor >= 0)
4938 qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4939 if (r_glsl_permutation->loc_ClientTime >= 0)
4940 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4941 if (r_glsl_permutation->loc_PixelSize >= 0)
4942 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4943 if (r_glsl_permutation->loc_UserVec1 >= 0)
4945 float a=0, b=0, c=0, d=0;
4946 #if _MSC_VER >= 1400
4947 #define sscanf sscanf_s
4949 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4950 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4952 if (r_glsl_permutation->loc_UserVec2 >= 0)
4954 float a=0, b=0, c=0, d=0;
4955 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4956 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4958 if (r_glsl_permutation->loc_UserVec3 >= 0)
4960 float a=0, b=0, c=0, d=0;
4961 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4962 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4964 if (r_glsl_permutation->loc_UserVec4 >= 0)
4966 float a=0, b=0, c=0, d=0;
4967 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4968 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4970 if (r_glsl_permutation->loc_Saturation >= 0)
4971 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4972 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4973 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4975 case RENDERPATH_GL13:
4976 case RENDERPATH_GL11:
4977 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4979 // apply a color tint to the whole view
4980 R_ResetViewRendering2D();
4981 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4982 R_Mesh_ColorPointer(NULL, 0, 0);
4983 R_SetupGenericShader(false);
4984 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4985 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4986 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4992 matrix4x4_t r_waterscrollmatrix;
4994 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4996 if (r_refdef.fog_density)
4998 r_refdef.fogcolor[0] = r_refdef.fog_red;
4999 r_refdef.fogcolor[1] = r_refdef.fog_green;
5000 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5002 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5003 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5004 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5005 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5009 VectorCopy(r_refdef.fogcolor, fogvec);
5010 // color.rgb *= ContrastBoost * SceneBrightness;
5011 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5012 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5013 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5014 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5019 void R_UpdateVariables(void)
5023 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
5025 r_refdef.farclip = r_farclip_base.value;
5026 if (r_refdef.scene.worldmodel)
5027 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5028 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5030 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5031 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5032 r_refdef.polygonfactor = 0;
5033 r_refdef.polygonoffset = 0;
5034 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5035 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5037 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5038 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5039 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5040 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5041 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5042 if (r_showsurfaces.integer)
5044 r_refdef.scene.rtworld = false;
5045 r_refdef.scene.rtworldshadows = false;
5046 r_refdef.scene.rtdlight = false;
5047 r_refdef.scene.rtdlightshadows = false;
5048 r_refdef.lightmapintensity = 0;
5051 if (gamemode == GAME_NEHAHRA)
5053 if (gl_fogenable.integer)
5055 r_refdef.oldgl_fogenable = true;
5056 r_refdef.fog_density = gl_fogdensity.value;
5057 r_refdef.fog_red = gl_fogred.value;
5058 r_refdef.fog_green = gl_foggreen.value;
5059 r_refdef.fog_blue = gl_fogblue.value;
5060 r_refdef.fog_alpha = 1;
5061 r_refdef.fog_start = 0;
5062 r_refdef.fog_end = gl_skyclip.value;
5063 r_refdef.fog_height = 1<<30;
5064 r_refdef.fog_fadedepth = 128;
5066 else if (r_refdef.oldgl_fogenable)
5068 r_refdef.oldgl_fogenable = false;
5069 r_refdef.fog_density = 0;
5070 r_refdef.fog_red = 0;
5071 r_refdef.fog_green = 0;
5072 r_refdef.fog_blue = 0;
5073 r_refdef.fog_alpha = 0;
5074 r_refdef.fog_start = 0;
5075 r_refdef.fog_end = 0;
5076 r_refdef.fog_height = 1<<30;
5077 r_refdef.fog_fadedepth = 128;
5081 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5082 r_refdef.fog_start = max(0, r_refdef.fog_start);
5083 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5085 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5087 if (r_refdef.fog_density && r_drawfog.integer)
5089 r_refdef.fogenabled = true;
5090 // this is the point where the fog reaches 0.9986 alpha, which we
5091 // consider a good enough cutoff point for the texture
5092 // (0.9986 * 256 == 255.6)
5093 if (r_fog_exp2.integer)
5094 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5096 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5097 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5098 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5099 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5100 // fog color was already set
5101 // update the fog texture
5102 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)
5103 R_BuildFogTexture();
5106 r_refdef.fogenabled = false;
5108 switch(vid.renderpath)
5110 case RENDERPATH_GL20:
5111 if(v_glslgamma.integer && !vid_gammatables_trivial)
5113 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5115 // build GLSL gamma texture
5116 #define RAMPWIDTH 256
5117 unsigned short ramp[RAMPWIDTH * 3];
5118 unsigned char rampbgr[RAMPWIDTH][4];
5121 r_texture_gammaramps_serial = vid_gammatables_serial;
5123 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5124 for(i = 0; i < RAMPWIDTH; ++i)
5126 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5127 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5128 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5131 if (r_texture_gammaramps)
5133 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5137 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
5143 // remove GLSL gamma texture
5146 case RENDERPATH_GL13:
5147 case RENDERPATH_GL11:
5152 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5153 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5159 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5160 if( scenetype != r_currentscenetype ) {
5161 // store the old scenetype
5162 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5163 r_currentscenetype = scenetype;
5164 // move in the new scene
5165 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5174 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5176 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5177 if( scenetype == r_currentscenetype ) {
5178 return &r_refdef.scene;
5180 return &r_scenes_store[ scenetype ];
5189 void R_RenderView(void)
5191 if (r_timereport_active)
5192 R_TimeReport("start");
5193 r_frame++; // used only by R_GetCurrentTexture
5194 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5196 if (!r_drawentities.integer)
5197 r_refdef.scene.numentities = 0;
5199 R_AnimCache_ClearCache();
5200 R_FrameData_NewFrame();
5202 if (r_refdef.view.isoverlay)
5204 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5205 GL_Clear( GL_DEPTH_BUFFER_BIT );
5206 R_TimeReport("depthclear");
5208 r_refdef.view.showdebug = false;
5210 r_waterstate.enabled = false;
5211 r_waterstate.numwaterplanes = 0;
5219 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
5220 return; //Host_Error ("R_RenderView: NULL worldmodel");
5222 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
5224 // break apart the view matrix into vectors for various purposes
5225 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5226 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5227 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5228 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5229 // make an inverted copy of the view matrix for tracking sprites
5230 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5232 R_Shadow_UpdateWorldLightSelection();
5234 R_Bloom_StartFrame();
5235 R_Water_StartFrame();
5238 if (r_timereport_active)
5239 R_TimeReport("viewsetup");
5241 R_ResetViewRendering3D();
5243 if (r_refdef.view.clear || r_refdef.fogenabled)
5245 R_ClearScreen(r_refdef.fogenabled);
5246 if (r_timereport_active)
5247 R_TimeReport("viewclear");
5249 r_refdef.view.clear = true;
5251 // this produces a bloom texture to be used in R_BlendView() later
5252 if (r_hdr.integer && r_bloomstate.bloomwidth)
5253 R_HDR_RenderBloomTexture();
5255 r_refdef.view.showdebug = true;
5258 if (r_timereport_active)
5259 R_TimeReport("visibility");
5261 r_waterstate.numwaterplanes = 0;
5262 if (r_waterstate.enabled)
5263 R_RenderWaterPlanes();
5266 r_waterstate.numwaterplanes = 0;
5269 if (r_timereport_active)
5270 R_TimeReport("blendview");
5272 GL_Scissor(0, 0, vid.width, vid.height);
5273 GL_ScissorTest(false);
5277 void R_RenderWaterPlanes(void)
5279 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
5281 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
5282 if (r_timereport_active)
5283 R_TimeReport("waterworld");
5286 // don't let sound skip if going slow
5287 if (r_refdef.scene.extraupdate)
5290 R_DrawModelsAddWaterPlanes();
5291 if (r_timereport_active)
5292 R_TimeReport("watermodels");
5294 if (r_waterstate.numwaterplanes)
5296 R_Water_ProcessPlanes();
5297 if (r_timereport_active)
5298 R_TimeReport("waterscenes");
5302 extern void R_DrawLightningBeams (void);
5303 extern void VM_CL_AddPolygonsToMeshQueue (void);
5304 extern void R_DrawPortals (void);
5305 extern cvar_t cl_locs_show;
5306 static void R_DrawLocs(void);
5307 static void R_DrawEntityBBoxes(void);
5308 static void R_DrawModelDecals(void);
5309 extern cvar_t cl_decals_newsystem;
5310 extern qboolean r_shadow_usingdeferredprepass;
5311 void R_RenderScene(void)
5313 r_refdef.stats.renders++;
5317 // don't let sound skip if going slow
5318 if (r_refdef.scene.extraupdate)
5321 R_MeshQueue_BeginScene();
5325 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);
5327 if (cl.csqc_vidvars.drawworld)
5329 // don't let sound skip if going slow
5330 if (r_refdef.scene.extraupdate)
5333 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5335 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5336 if (r_timereport_active)
5337 R_TimeReport("worldsky");
5340 if (R_DrawBrushModelsSky() && r_timereport_active)
5341 R_TimeReport("bmodelsky");
5343 if (skyrendermasked && skyrenderlater)
5345 // we have to force off the water clipping plane while rendering sky
5349 if (r_timereport_active)
5350 R_TimeReport("sky");
5354 R_AnimCache_CacheVisibleEntities();
5355 if (r_timereport_active)
5356 R_TimeReport("animation");
5358 R_Shadow_PrepareLights();
5359 if (r_timereport_active)
5360 R_TimeReport("preparelights");
5362 if (r_shadow_usingdeferredprepass)
5363 R_Shadow_DrawPrepass();
5365 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5367 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5368 if (r_timereport_active)
5369 R_TimeReport("worlddepth");
5371 if (r_depthfirst.integer >= 2)
5373 R_DrawModelsDepth();
5374 if (r_timereport_active)
5375 R_TimeReport("modeldepth");
5378 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5380 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5381 if (r_timereport_active)
5382 R_TimeReport("world");
5385 // don't let sound skip if going slow
5386 if (r_refdef.scene.extraupdate)
5390 if (r_timereport_active)
5391 R_TimeReport("models");
5393 // don't let sound skip if going slow
5394 if (r_refdef.scene.extraupdate)
5397 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5399 R_DrawModelShadows();
5400 R_ResetViewRendering3D();
5401 // don't let sound skip if going slow
5402 if (r_refdef.scene.extraupdate)
5406 if (!r_shadow_usingdeferredprepass)
5408 R_Shadow_DrawLights();
5409 if (r_timereport_active)
5410 R_TimeReport("rtlights");
5413 // don't let sound skip if going slow
5414 if (r_refdef.scene.extraupdate)
5417 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5419 R_DrawModelShadows();
5420 R_ResetViewRendering3D();
5421 // don't let sound skip if going slow
5422 if (r_refdef.scene.extraupdate)
5426 if (cl.csqc_vidvars.drawworld)
5428 if (cl_decals_newsystem.integer)
5430 R_DrawModelDecals();
5431 if (r_timereport_active)
5432 R_TimeReport("modeldecals");
5437 if (r_timereport_active)
5438 R_TimeReport("decals");
5442 if (r_timereport_active)
5443 R_TimeReport("particles");
5446 if (r_timereport_active)
5447 R_TimeReport("explosions");
5449 R_DrawLightningBeams();
5450 if (r_timereport_active)
5451 R_TimeReport("lightning");
5454 R_SetupGenericShader(true);
5455 VM_CL_AddPolygonsToMeshQueue();
5457 if (r_refdef.view.showdebug)
5459 if (cl_locs_show.integer)
5462 if (r_timereport_active)
5463 R_TimeReport("showlocs");
5466 if (r_drawportals.integer)
5469 if (r_timereport_active)
5470 R_TimeReport("portals");
5473 if (r_showbboxes.value > 0)
5475 R_DrawEntityBBoxes();
5476 if (r_timereport_active)
5477 R_TimeReport("bboxes");
5481 R_SetupGenericShader(true);
5482 R_MeshQueue_RenderTransparent();
5483 if (r_timereport_active)
5484 R_TimeReport("drawtrans");
5486 R_SetupGenericShader(true);
5488 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))
5490 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5491 if (r_timereport_active)
5492 R_TimeReport("worlddebug");
5493 R_DrawModelsDebug();
5494 if (r_timereport_active)
5495 R_TimeReport("modeldebug");
5498 R_SetupGenericShader(true);
5500 if (cl.csqc_vidvars.drawworld)
5502 R_Shadow_DrawCoronas();
5503 if (r_timereport_active)
5504 R_TimeReport("coronas");
5507 // don't let sound skip if going slow
5508 if (r_refdef.scene.extraupdate)
5511 R_ResetViewRendering2D();
5514 static const unsigned short bboxelements[36] =
5524 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5527 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5529 RSurf_ActiveWorldEntity();
5531 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5532 GL_DepthMask(false);
5533 GL_DepthRange(0, 1);
5534 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5535 R_Mesh_ResetTextureState();
5537 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5538 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5539 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5540 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5541 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5542 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5543 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5544 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5545 R_FillColors(color4f, 8, cr, cg, cb, ca);
5546 if (r_refdef.fogenabled)
5548 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5550 f1 = RSurf_FogVertex(v);
5552 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5553 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5554 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5557 R_Mesh_VertexPointer(vertex3f, 0, 0);
5558 R_Mesh_ColorPointer(color4f, 0, 0);
5559 R_Mesh_ResetTextureState();
5560 R_SetupGenericShader(false);
5561 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5564 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5568 prvm_edict_t *edict;
5569 prvm_prog_t *prog_save = prog;
5571 // this function draws bounding boxes of server entities
5575 GL_CullFace(GL_NONE);
5576 R_SetupGenericShader(false);
5580 for (i = 0;i < numsurfaces;i++)
5582 edict = PRVM_EDICT_NUM(surfacelist[i]);
5583 switch ((int)edict->fields.server->solid)
5585 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
5586 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
5587 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
5588 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5589 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
5590 default: Vector4Set(color, 0, 0, 0, 0.50);break;
5592 color[3] *= r_showbboxes.value;
5593 color[3] = bound(0, color[3], 1);
5594 GL_DepthTest(!r_showdisabledepthtest.integer);
5595 GL_CullFace(r_refdef.view.cullface_front);
5596 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5602 static void R_DrawEntityBBoxes(void)
5605 prvm_edict_t *edict;
5607 prvm_prog_t *prog_save = prog;
5609 // this function draws bounding boxes of server entities
5615 for (i = 0;i < prog->num_edicts;i++)
5617 edict = PRVM_EDICT_NUM(i);
5618 if (edict->priv.server->free)
5620 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5621 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5623 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5625 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5626 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5632 static const int nomodelelement3i[24] =
5644 static const unsigned short nomodelelement3s[24] =
5656 static const float nomodelvertex3f[6*3] =
5666 static const float nomodelcolor4f[6*4] =
5668 0.0f, 0.0f, 0.5f, 1.0f,
5669 0.0f, 0.0f, 0.5f, 1.0f,
5670 0.0f, 0.5f, 0.0f, 1.0f,
5671 0.0f, 0.5f, 0.0f, 1.0f,
5672 0.5f, 0.0f, 0.0f, 1.0f,
5673 0.5f, 0.0f, 0.0f, 1.0f
5676 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5682 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);
5684 // this is only called once per entity so numsurfaces is always 1, and
5685 // surfacelist is always {0}, so this code does not handle batches
5687 if (rsurface.ent_flags & RENDER_ADDITIVE)
5689 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5690 GL_DepthMask(false);
5692 else if (rsurface.colormod[3] < 1)
5694 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5695 GL_DepthMask(false);
5699 GL_BlendFunc(GL_ONE, GL_ZERO);
5702 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5703 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5704 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5705 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5706 R_SetupGenericShader(false);
5707 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5708 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5709 R_Mesh_ColorPointer(color4f, 0, 0);
5710 for (i = 0, c = color4f;i < 6;i++, c += 4)
5712 c[0] *= rsurface.colormod[0];
5713 c[1] *= rsurface.colormod[1];
5714 c[2] *= rsurface.colormod[2];
5715 c[3] *= rsurface.colormod[3];
5717 if (r_refdef.fogenabled)
5719 for (i = 0, c = color4f;i < 6;i++, c += 4)
5721 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5723 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5724 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5725 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5728 R_Mesh_ResetTextureState();
5729 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5732 void R_DrawNoModel(entity_render_t *ent)
5735 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5736 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5737 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5739 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5742 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5744 vec3_t right1, right2, diff, normal;
5746 VectorSubtract (org2, org1, normal);
5748 // calculate 'right' vector for start
5749 VectorSubtract (r_refdef.view.origin, org1, diff);
5750 CrossProduct (normal, diff, right1);
5751 VectorNormalize (right1);
5753 // calculate 'right' vector for end
5754 VectorSubtract (r_refdef.view.origin, org2, diff);
5755 CrossProduct (normal, diff, right2);
5756 VectorNormalize (right2);
5758 vert[ 0] = org1[0] + width * right1[0];
5759 vert[ 1] = org1[1] + width * right1[1];
5760 vert[ 2] = org1[2] + width * right1[2];
5761 vert[ 3] = org1[0] - width * right1[0];
5762 vert[ 4] = org1[1] - width * right1[1];
5763 vert[ 5] = org1[2] - width * right1[2];
5764 vert[ 6] = org2[0] - width * right2[0];
5765 vert[ 7] = org2[1] - width * right2[1];
5766 vert[ 8] = org2[2] - width * right2[2];
5767 vert[ 9] = org2[0] + width * right2[0];
5768 vert[10] = org2[1] + width * right2[1];
5769 vert[11] = org2[2] + width * right2[2];
5772 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)
5774 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5775 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5776 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5777 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5778 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5779 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5780 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5781 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5782 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5783 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5784 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5785 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5788 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5793 VectorSet(v, x, y, z);
5794 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5795 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5797 if (i == mesh->numvertices)
5799 if (mesh->numvertices < mesh->maxvertices)
5801 VectorCopy(v, vertex3f);
5802 mesh->numvertices++;
5804 return mesh->numvertices;
5810 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5814 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5815 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5816 e = mesh->element3i + mesh->numtriangles * 3;
5817 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5819 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5820 if (mesh->numtriangles < mesh->maxtriangles)
5825 mesh->numtriangles++;
5827 element[1] = element[2];
5831 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5835 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5836 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5837 e = mesh->element3i + mesh->numtriangles * 3;
5838 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5840 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5841 if (mesh->numtriangles < mesh->maxtriangles)
5846 mesh->numtriangles++;
5848 element[1] = element[2];
5852 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5853 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5855 int planenum, planenum2;
5858 mplane_t *plane, *plane2;
5860 double temppoints[2][256*3];
5861 // figure out how large a bounding box we need to properly compute this brush
5863 for (w = 0;w < numplanes;w++)
5864 maxdist = max(maxdist, fabs(planes[w].dist));
5865 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5866 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5867 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5871 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5872 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5874 if (planenum2 == planenum)
5876 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);
5879 if (tempnumpoints < 3)
5881 // generate elements forming a triangle fan for this polygon
5882 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5886 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)
5888 texturelayer_t *layer;
5889 layer = t->currentlayers + t->currentnumlayers++;
5891 layer->depthmask = depthmask;
5892 layer->blendfunc1 = blendfunc1;
5893 layer->blendfunc2 = blendfunc2;
5894 layer->texture = texture;
5895 layer->texmatrix = *matrix;
5896 layer->color[0] = r;
5897 layer->color[1] = g;
5898 layer->color[2] = b;
5899 layer->color[3] = a;
5902 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5905 index = parms[2] + r_refdef.scene.time * parms[3];
5906 index -= floor(index);
5910 case Q3WAVEFUNC_NONE:
5911 case Q3WAVEFUNC_NOISE:
5912 case Q3WAVEFUNC_COUNT:
5915 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5916 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5917 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5918 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5919 case Q3WAVEFUNC_TRIANGLE:
5921 f = index - floor(index);
5932 return (float)(parms[0] + parms[1] * f);
5935 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5940 matrix4x4_t matrix, temp;
5941 switch(tcmod->tcmod)
5945 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5946 matrix = r_waterscrollmatrix;
5948 matrix = identitymatrix;
5950 case Q3TCMOD_ENTITYTRANSLATE:
5951 // this is used in Q3 to allow the gamecode to control texcoord
5952 // scrolling on the entity, which is not supported in darkplaces yet.
5953 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5955 case Q3TCMOD_ROTATE:
5956 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5957 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5958 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5961 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5963 case Q3TCMOD_SCROLL:
5964 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5966 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5967 w = (int) tcmod->parms[0];
5968 h = (int) tcmod->parms[1];
5969 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5971 idx = (int) floor(f * w * h);
5972 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5974 case Q3TCMOD_STRETCH:
5975 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5976 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5978 case Q3TCMOD_TRANSFORM:
5979 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5980 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5981 VectorSet(tcmat + 6, 0 , 0 , 1);
5982 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5983 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5985 case Q3TCMOD_TURBULENT:
5986 // this is handled in the RSurf_PrepareVertices function
5987 matrix = identitymatrix;
5991 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5994 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5996 int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5997 char name[MAX_QPATH];
5998 skinframe_t *skinframe;
5999 unsigned char pixels[296*194];
6000 strlcpy(cache->name, skinname, sizeof(cache->name));
6001 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6002 if (developer_loading.integer)
6003 Con_Printf("loading %s\n", name);
6004 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6005 if (!skinframe || !skinframe->base)
6008 fs_offset_t filesize;
6010 f = FS_LoadFile(name, tempmempool, true, &filesize);
6013 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
6014 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6018 cache->skinframe = skinframe;
6021 texture_t *R_GetCurrentTexture(texture_t *t)
6024 const entity_render_t *ent = rsurface.entity;
6025 dp_model_t *model = ent->model;
6026 q3shaderinfo_layer_tcmod_t *tcmod;
6028 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
6029 return t->currentframe;
6030 t->update_lastrenderframe = r_frame;
6031 t->update_lastrenderentity = (void *)ent;
6033 // switch to an alternate material if this is a q1bsp animated material
6035 texture_t *texture = t;
6036 int s = rsurface.ent_skinnum;
6037 if ((unsigned int)s >= (unsigned int)model->numskins)
6039 if (model->skinscenes)
6041 if (model->skinscenes[s].framecount > 1)
6042 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6044 s = model->skinscenes[s].firstframe;
6047 t = t + s * model->num_surfaces;
6050 // use an alternate animation if the entity's frame is not 0,
6051 // and only if the texture has an alternate animation
6052 if (rsurface.ent_alttextures && t->anim_total[1])
6053 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6055 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6057 texture->currentframe = t;
6060 // update currentskinframe to be a qw skin or animation frame
6061 if (rsurface.ent_qwskin >= 0)
6063 i = rsurface.ent_qwskin;
6064 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6066 r_qwskincache_size = cl.maxclients;
6068 Mem_Free(r_qwskincache);
6069 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6071 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6072 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6073 t->currentskinframe = r_qwskincache[i].skinframe;
6074 if (t->currentskinframe == NULL)
6075 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6077 else if (t->numskinframes >= 2)
6078 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6079 if (t->backgroundnumskinframes >= 2)
6080 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6082 t->currentmaterialflags = t->basematerialflags;
6083 t->currentalpha = rsurface.colormod[3];
6084 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6085 t->currentalpha *= r_wateralpha.value;
6086 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6087 t->currentalpha *= t->r_water_wateralpha;
6088 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6089 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6090 if (!(rsurface.ent_flags & RENDER_LIGHT))
6091 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6092 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6094 // pick a model lighting mode
6095 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6096 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6098 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6100 if (rsurface.ent_flags & RENDER_ADDITIVE)
6101 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6102 else if (t->currentalpha < 1)
6103 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6104 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6105 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6106 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6107 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6108 if (t->backgroundnumskinframes)
6109 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6110 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6112 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6113 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6116 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6117 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6118 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6120 // there is no tcmod
6121 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6123 t->currenttexmatrix = r_waterscrollmatrix;
6124 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6126 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6128 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6129 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6132 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6133 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6134 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6135 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6137 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6138 if (t->currentskinframe->qpixels)
6139 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6140 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6141 t->glosstexture = r_texture_black;
6142 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6143 t->backgroundglosstexture = r_texture_black;
6144 t->specularpower = r_shadow_glossexponent.value;
6145 // TODO: store reference values for these in the texture?
6146 t->specularscale = 0;
6147 if (r_shadow_gloss.integer > 0)
6149 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6151 if (r_shadow_glossintensity.value > 0)
6153 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6154 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6155 t->specularscale = r_shadow_glossintensity.value;
6158 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6160 t->glosstexture = r_texture_white;
6161 t->backgroundglosstexture = r_texture_white;
6162 t->specularscale = r_shadow_gloss2intensity.value;
6163 t->specularpower = r_shadow_gloss2exponent.value;
6166 t->specularscale *= t->specularscalemod;
6167 t->specularpower *= t->specularpowermod;
6169 // lightmaps mode looks bad with dlights using actual texturing, so turn
6170 // off the colormap and glossmap, but leave the normalmap on as it still
6171 // accurately represents the shading involved
6172 if (gl_lightmaps.integer)
6174 t->basetexture = r_texture_grey128;
6175 t->backgroundbasetexture = NULL;
6176 t->specularscale = 0;
6177 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6180 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
6181 VectorClear(t->dlightcolor);
6182 t->currentnumlayers = 0;
6183 if (t->currentmaterialflags & MATERIALFLAG_WALL)
6185 int blendfunc1, blendfunc2;
6187 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6189 blendfunc1 = GL_SRC_ALPHA;
6190 blendfunc2 = GL_ONE;
6192 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6194 blendfunc1 = GL_SRC_ALPHA;
6195 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6197 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6199 blendfunc1 = t->customblendfunc[0];
6200 blendfunc2 = t->customblendfunc[1];
6204 blendfunc1 = GL_ONE;
6205 blendfunc2 = GL_ZERO;
6207 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
6208 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
6210 // fullbright is not affected by r_refdef.lightmapintensity
6211 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]);
6212 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6213 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]);
6214 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6215 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]);
6219 vec3_t ambientcolor;
6221 // set the color tint used for lights affecting this surface
6222 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
6224 // q3bsp has no lightmap updates, so the lightstylevalue that
6225 // would normally be baked into the lightmap must be
6226 // applied to the color
6227 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
6228 if (model->type == mod_brushq3)
6229 colorscale *= r_refdef.scene.rtlightstylevalue[0];
6230 colorscale *= r_refdef.lightmapintensity;
6231 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
6232 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
6233 // basic lit geometry
6234 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]);
6235 // add pants/shirt if needed
6236 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6237 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]);
6238 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6239 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]);
6240 // now add ambient passes if needed
6241 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
6243 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]);
6244 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
6245 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]);
6246 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
6247 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]);
6250 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
6251 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]);
6252 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
6254 // if this is opaque use alpha blend which will darken the earlier
6257 // if this is an alpha blended material, all the earlier passes
6258 // were darkened by fog already, so we only need to add the fog
6259 // color ontop through the fog mask texture
6261 // if this is an additive blended material, all the earlier passes
6262 // were darkened by fog already, and we should not add fog color
6263 // (because the background was not darkened, there is no fog color
6264 // that was lost behind it).
6265 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &t->currenttexmatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]);
6269 return t->currentframe;
6272 rsurfacestate_t rsurface;
6274 void R_Mesh_ResizeArrays(int newvertices)
6277 if (rsurface.array_size >= newvertices)
6279 if (rsurface.array_modelvertex3f)
6280 Mem_Free(rsurface.array_modelvertex3f);
6281 rsurface.array_size = (newvertices + 1023) & ~1023;
6282 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
6283 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
6284 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
6285 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
6286 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
6287 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
6288 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
6289 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
6290 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
6291 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
6292 rsurface.array_color4f = base + rsurface.array_size * 27;
6293 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
6296 void RSurf_ActiveWorldEntity(void)
6298 dp_model_t *model = r_refdef.scene.worldmodel;
6299 //if (rsurface.entity == r_refdef.scene.worldentity)
6301 rsurface.entity = r_refdef.scene.worldentity;
6302 rsurface.skeleton = NULL;
6303 rsurface.ent_skinnum = 0;
6304 rsurface.ent_qwskin = -1;
6305 rsurface.ent_shadertime = 0;
6306 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6307 if (rsurface.array_size < model->surfmesh.num_vertices)
6308 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6309 rsurface.matrix = identitymatrix;
6310 rsurface.inversematrix = identitymatrix;
6311 rsurface.matrixscale = 1;
6312 rsurface.inversematrixscale = 1;
6313 R_Mesh_Matrix(&identitymatrix);
6314 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6315 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6316 rsurface.fograngerecip = r_refdef.fograngerecip;
6317 rsurface.fogheightfade = r_refdef.fogheightfade;
6318 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6319 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6320 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6321 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6322 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6323 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6324 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6325 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
6326 rsurface.colormod[3] = 1;
6327 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);
6328 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6329 rsurface.frameblend[0].lerp = 1;
6330 rsurface.ent_alttextures = false;
6331 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6332 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6333 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6334 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6335 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6336 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6337 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6338 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6339 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6340 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6341 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6342 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6343 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6344 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6345 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6346 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6347 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6348 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6349 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6350 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6351 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6352 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6353 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6354 rsurface.modelelement3i = model->surfmesh.data_element3i;
6355 rsurface.modelelement3s = model->surfmesh.data_element3s;
6356 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6357 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6358 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6359 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6360 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6361 rsurface.modelsurfaces = model->data_surfaces;
6362 rsurface.generatedvertex = false;
6363 rsurface.vertex3f = rsurface.modelvertex3f;
6364 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6365 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6366 rsurface.svector3f = rsurface.modelsvector3f;
6367 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6368 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6369 rsurface.tvector3f = rsurface.modeltvector3f;
6370 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6371 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6372 rsurface.normal3f = rsurface.modelnormal3f;
6373 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6374 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6375 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6378 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
6380 dp_model_t *model = ent->model;
6381 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6383 rsurface.entity = (entity_render_t *)ent;
6384 rsurface.skeleton = ent->skeleton;
6385 rsurface.ent_skinnum = ent->skinnum;
6386 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;
6387 rsurface.ent_shadertime = ent->shadertime;
6388 rsurface.ent_flags = ent->flags;
6389 if (rsurface.array_size < model->surfmesh.num_vertices)
6390 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6391 rsurface.matrix = ent->matrix;
6392 rsurface.inversematrix = ent->inversematrix;
6393 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6394 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6395 R_Mesh_Matrix(&rsurface.matrix);
6396 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6397 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6398 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6399 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6400 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6401 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6402 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6403 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6404 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6405 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6406 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6407 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
6408 rsurface.colormod[3] = ent->alpha;
6409 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
6410 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6411 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6412 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6413 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6414 if (ent->model->brush.submodel && !prepass)
6416 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6417 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6419 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6421 if (ent->animcache_vertex3f && !r_framedata_failed)
6423 rsurface.modelvertex3f = ent->animcache_vertex3f;
6424 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
6425 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
6426 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
6428 else if (wanttangents)
6430 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6431 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6432 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6433 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6434 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6436 else if (wantnormals)
6438 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6439 rsurface.modelsvector3f = NULL;
6440 rsurface.modeltvector3f = NULL;
6441 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6442 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6446 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6447 rsurface.modelsvector3f = NULL;
6448 rsurface.modeltvector3f = NULL;
6449 rsurface.modelnormal3f = NULL;
6450 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6452 rsurface.modelvertex3f_bufferobject = 0;
6453 rsurface.modelvertex3f_bufferoffset = 0;
6454 rsurface.modelsvector3f_bufferobject = 0;
6455 rsurface.modelsvector3f_bufferoffset = 0;
6456 rsurface.modeltvector3f_bufferobject = 0;
6457 rsurface.modeltvector3f_bufferoffset = 0;
6458 rsurface.modelnormal3f_bufferobject = 0;
6459 rsurface.modelnormal3f_bufferoffset = 0;
6460 rsurface.generatedvertex = true;
6464 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
6465 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6466 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6467 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6468 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6469 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6470 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6471 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6472 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6473 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
6474 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6475 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6476 rsurface.generatedvertex = false;
6478 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
6479 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6480 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6481 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
6482 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6483 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6484 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
6485 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6486 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6487 rsurface.modelelement3i = model->surfmesh.data_element3i;
6488 rsurface.modelelement3s = model->surfmesh.data_element3s;
6489 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6490 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6491 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6492 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6493 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6494 rsurface.modelsurfaces = model->data_surfaces;
6495 rsurface.vertex3f = rsurface.modelvertex3f;
6496 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6497 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6498 rsurface.svector3f = rsurface.modelsvector3f;
6499 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6500 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6501 rsurface.tvector3f = rsurface.modeltvector3f;
6502 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6503 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6504 rsurface.normal3f = rsurface.modelnormal3f;
6505 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6506 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6507 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6510 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)
6512 rsurface.entity = r_refdef.scene.worldentity;
6513 rsurface.skeleton = NULL;
6514 rsurface.ent_skinnum = 0;
6515 rsurface.ent_qwskin = -1;
6516 rsurface.ent_shadertime = shadertime;
6517 rsurface.ent_flags = entflags;
6518 rsurface.modelnum_vertices = numvertices;
6519 rsurface.modelnum_triangles = numtriangles;
6520 if (rsurface.array_size < rsurface.modelnum_vertices)
6521 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6522 rsurface.matrix = *matrix;
6523 rsurface.inversematrix = *inversematrix;
6524 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6525 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6526 R_Mesh_Matrix(&rsurface.matrix);
6527 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6528 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6529 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6530 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6531 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6532 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6533 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6534 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6535 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6536 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6537 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6538 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
6539 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);
6540 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6541 rsurface.frameblend[0].lerp = 1;
6542 rsurface.ent_alttextures = false;
6543 rsurface.basepolygonfactor = r_refdef.polygonfactor;
6544 rsurface.basepolygonoffset = r_refdef.polygonoffset;
6547 rsurface.modelvertex3f = vertex3f;
6548 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6549 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6550 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6552 else if (wantnormals)
6554 rsurface.modelvertex3f = vertex3f;
6555 rsurface.modelsvector3f = NULL;
6556 rsurface.modeltvector3f = NULL;
6557 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6561 rsurface.modelvertex3f = vertex3f;
6562 rsurface.modelsvector3f = NULL;
6563 rsurface.modeltvector3f = NULL;
6564 rsurface.modelnormal3f = NULL;
6566 rsurface.modelvertex3f_bufferobject = 0;
6567 rsurface.modelvertex3f_bufferoffset = 0;
6568 rsurface.modelsvector3f_bufferobject = 0;
6569 rsurface.modelsvector3f_bufferoffset = 0;
6570 rsurface.modeltvector3f_bufferobject = 0;
6571 rsurface.modeltvector3f_bufferoffset = 0;
6572 rsurface.modelnormal3f_bufferobject = 0;
6573 rsurface.modelnormal3f_bufferoffset = 0;
6574 rsurface.generatedvertex = true;
6575 rsurface.modellightmapcolor4f = color4f;
6576 rsurface.modellightmapcolor4f_bufferobject = 0;
6577 rsurface.modellightmapcolor4f_bufferoffset = 0;
6578 rsurface.modeltexcoordtexture2f = texcoord2f;
6579 rsurface.modeltexcoordtexture2f_bufferobject = 0;
6580 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6581 rsurface.modeltexcoordlightmap2f = NULL;
6582 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6583 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6584 rsurface.modelelement3i = element3i;
6585 rsurface.modelelement3s = element3s;
6586 rsurface.modelelement3i_bufferobject = 0;
6587 rsurface.modelelement3s_bufferobject = 0;
6588 rsurface.modellightmapoffsets = NULL;
6589 rsurface.modelsurfaces = NULL;
6590 rsurface.vertex3f = rsurface.modelvertex3f;
6591 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6592 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6593 rsurface.svector3f = rsurface.modelsvector3f;
6594 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6595 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6596 rsurface.tvector3f = rsurface.modeltvector3f;
6597 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6598 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6599 rsurface.normal3f = rsurface.modelnormal3f;
6600 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6601 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6602 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6604 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6606 if ((wantnormals || wanttangents) && !normal3f)
6607 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6608 if (wanttangents && !svector3f)
6609 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);
6613 float RSurf_FogPoint(const float *v)
6615 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6616 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6617 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6618 float FogHeightFade = r_refdef.fogheightfade;
6620 unsigned int fogmasktableindex;
6621 if (r_refdef.fogplaneviewabove)
6622 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6624 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6625 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6626 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6629 float RSurf_FogVertex(const float *v)
6631 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6632 float FogPlaneViewDist = rsurface.fogplaneviewdist;
6633 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6634 float FogHeightFade = rsurface.fogheightfade;
6636 unsigned int fogmasktableindex;
6637 if (r_refdef.fogplaneviewabove)
6638 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6640 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6641 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6642 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6645 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6646 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6649 int texturesurfaceindex;
6654 const float *v1, *in_tc;
6656 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6658 q3shaderinfo_deform_t *deform;
6659 // 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
6660 if (rsurface.generatedvertex)
6662 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6663 generatenormals = true;
6664 for (i = 0;i < Q3MAXDEFORMS;i++)
6666 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6668 generatetangents = true;
6669 generatenormals = true;
6671 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6672 generatenormals = true;
6674 if (generatenormals && !rsurface.modelnormal3f)
6676 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6677 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6678 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6679 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6681 if (generatetangents && !rsurface.modelsvector3f)
6683 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6684 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6685 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6686 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6687 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6688 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6689 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);
6692 rsurface.vertex3f = rsurface.modelvertex3f;
6693 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6694 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6695 rsurface.svector3f = rsurface.modelsvector3f;
6696 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6697 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6698 rsurface.tvector3f = rsurface.modeltvector3f;
6699 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6700 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6701 rsurface.normal3f = rsurface.modelnormal3f;
6702 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6703 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6704 // if vertices are deformed (sprite flares and things in maps, possibly
6705 // water waves, bulges and other deformations), generate them into
6706 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6707 // (may be static model data or generated data for an animated model, or
6708 // the previous deform pass)
6709 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6711 switch (deform->deform)
6714 case Q3DEFORM_PROJECTIONSHADOW:
6715 case Q3DEFORM_TEXT0:
6716 case Q3DEFORM_TEXT1:
6717 case Q3DEFORM_TEXT2:
6718 case Q3DEFORM_TEXT3:
6719 case Q3DEFORM_TEXT4:
6720 case Q3DEFORM_TEXT5:
6721 case Q3DEFORM_TEXT6:
6722 case Q3DEFORM_TEXT7:
6725 case Q3DEFORM_AUTOSPRITE:
6726 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6727 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6728 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6729 VectorNormalize(newforward);
6730 VectorNormalize(newright);
6731 VectorNormalize(newup);
6732 // make deformed versions of only the model vertices used by the specified surfaces
6733 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6735 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6736 // a single autosprite surface can contain multiple sprites...
6737 for (j = 0;j < surface->num_vertices - 3;j += 4)
6739 VectorClear(center);
6740 for (i = 0;i < 4;i++)
6741 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6742 VectorScale(center, 0.25f, center);
6743 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
6744 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6745 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6746 for (i = 0;i < 4;i++)
6748 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6749 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6752 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);
6753 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);
6755 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6756 rsurface.vertex3f_bufferobject = 0;
6757 rsurface.vertex3f_bufferoffset = 0;
6758 rsurface.svector3f = rsurface.array_deformedsvector3f;
6759 rsurface.svector3f_bufferobject = 0;
6760 rsurface.svector3f_bufferoffset = 0;
6761 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6762 rsurface.tvector3f_bufferobject = 0;
6763 rsurface.tvector3f_bufferoffset = 0;
6764 rsurface.normal3f = rsurface.array_deformednormal3f;
6765 rsurface.normal3f_bufferobject = 0;
6766 rsurface.normal3f_bufferoffset = 0;
6768 case Q3DEFORM_AUTOSPRITE2:
6769 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6770 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6771 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6772 VectorNormalize(newforward);
6773 VectorNormalize(newright);
6774 VectorNormalize(newup);
6775 // make deformed versions of only the model vertices used by the specified surfaces
6776 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6778 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6779 const float *v1, *v2;
6789 memset(shortest, 0, sizeof(shortest));
6790 // a single autosprite surface can contain multiple sprites...
6791 for (j = 0;j < surface->num_vertices - 3;j += 4)
6793 VectorClear(center);
6794 for (i = 0;i < 4;i++)
6795 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6796 VectorScale(center, 0.25f, center);
6797 // find the two shortest edges, then use them to define the
6798 // axis vectors for rotating around the central axis
6799 for (i = 0;i < 6;i++)
6801 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6802 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6804 Debug_PolygonBegin(NULL, 0);
6805 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6806 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);
6807 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6810 l = VectorDistance2(v1, v2);
6811 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6813 l += (1.0f / 1024.0f);
6814 if (shortest[0].length2 > l || i == 0)
6816 shortest[1] = shortest[0];
6817 shortest[0].length2 = l;
6818 shortest[0].v1 = v1;
6819 shortest[0].v2 = v2;
6821 else if (shortest[1].length2 > l || i == 1)
6823 shortest[1].length2 = l;
6824 shortest[1].v1 = v1;
6825 shortest[1].v2 = v2;
6828 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6829 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6831 Debug_PolygonBegin(NULL, 0);
6832 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6833 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);
6834 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6837 // this calculates the right vector from the shortest edge
6838 // and the up vector from the edge midpoints
6839 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6840 VectorNormalize(right);
6841 VectorSubtract(end, start, up);
6842 VectorNormalize(up);
6843 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6844 VectorSubtract(rsurface.localvieworigin, center, forward);
6845 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6846 VectorNegate(forward, forward);
6847 VectorReflect(forward, 0, up, forward);
6848 VectorNormalize(forward);
6849 CrossProduct(up, forward, newright);
6850 VectorNormalize(newright);
6852 Debug_PolygonBegin(NULL, 0);
6853 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);
6854 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6855 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6859 Debug_PolygonBegin(NULL, 0);
6860 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6861 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6862 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6865 // rotate the quad around the up axis vector, this is made
6866 // especially easy by the fact we know the quad is flat,
6867 // so we only have to subtract the center position and
6868 // measure distance along the right vector, and then
6869 // multiply that by the newright vector and add back the
6871 // we also need to subtract the old position to undo the
6872 // displacement from the center, which we do with a
6873 // DotProduct, the subtraction/addition of center is also
6874 // optimized into DotProducts here
6875 l = DotProduct(right, center);
6876 for (i = 0;i < 4;i++)
6878 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6879 f = DotProduct(right, v1) - l;
6880 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6883 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);
6884 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);
6886 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6887 rsurface.vertex3f_bufferobject = 0;
6888 rsurface.vertex3f_bufferoffset = 0;
6889 rsurface.svector3f = rsurface.array_deformedsvector3f;
6890 rsurface.svector3f_bufferobject = 0;
6891 rsurface.svector3f_bufferoffset = 0;
6892 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6893 rsurface.tvector3f_bufferobject = 0;
6894 rsurface.tvector3f_bufferoffset = 0;
6895 rsurface.normal3f = rsurface.array_deformednormal3f;
6896 rsurface.normal3f_bufferobject = 0;
6897 rsurface.normal3f_bufferoffset = 0;
6899 case Q3DEFORM_NORMAL:
6900 // deform the normals to make reflections wavey
6901 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6903 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6904 for (j = 0;j < surface->num_vertices;j++)
6907 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6908 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6909 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6910 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6911 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6912 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6913 VectorNormalize(normal);
6915 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);
6917 rsurface.svector3f = rsurface.array_deformedsvector3f;
6918 rsurface.svector3f_bufferobject = 0;
6919 rsurface.svector3f_bufferoffset = 0;
6920 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6921 rsurface.tvector3f_bufferobject = 0;
6922 rsurface.tvector3f_bufferoffset = 0;
6923 rsurface.normal3f = rsurface.array_deformednormal3f;
6924 rsurface.normal3f_bufferobject = 0;
6925 rsurface.normal3f_bufferoffset = 0;
6928 // deform vertex array to make wavey water and flags and such
6929 waveparms[0] = deform->waveparms[0];
6930 waveparms[1] = deform->waveparms[1];
6931 waveparms[2] = deform->waveparms[2];
6932 waveparms[3] = deform->waveparms[3];
6933 // this is how a divisor of vertex influence on deformation
6934 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6935 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6936 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6938 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6939 for (j = 0;j < surface->num_vertices;j++)
6941 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6942 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6943 // if the wavefunc depends on time, evaluate it per-vertex
6946 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6947 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6949 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6952 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6953 rsurface.vertex3f_bufferobject = 0;
6954 rsurface.vertex3f_bufferoffset = 0;
6956 case Q3DEFORM_BULGE:
6957 // deform vertex array to make the surface have moving bulges
6958 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6960 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6961 for (j = 0;j < surface->num_vertices;j++)
6963 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6964 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6967 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6968 rsurface.vertex3f_bufferobject = 0;
6969 rsurface.vertex3f_bufferoffset = 0;
6972 // deform vertex array
6973 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6974 VectorScale(deform->parms, scale, waveparms);
6975 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6977 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6978 for (j = 0;j < surface->num_vertices;j++)
6979 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6981 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6982 rsurface.vertex3f_bufferobject = 0;
6983 rsurface.vertex3f_bufferoffset = 0;
6987 // generate texcoords based on the chosen texcoord source
6988 switch(rsurface.texture->tcgen.tcgen)
6991 case Q3TCGEN_TEXTURE:
6992 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6993 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6994 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6996 case Q3TCGEN_LIGHTMAP:
6997 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6998 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6999 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7001 case Q3TCGEN_VECTOR:
7002 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7004 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7005 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)
7007 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
7008 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
7011 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7012 rsurface.texcoordtexture2f_bufferobject = 0;
7013 rsurface.texcoordtexture2f_bufferoffset = 0;
7015 case Q3TCGEN_ENVIRONMENT:
7016 // make environment reflections using a spheremap
7017 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7019 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7020 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
7021 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
7022 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
7023 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
7025 // identical to Q3A's method, but executed in worldspace so
7026 // carried models can be shiny too
7028 float viewer[3], d, reflected[3], worldreflected[3];
7030 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
7031 // VectorNormalize(viewer);
7033 d = DotProduct(normal, viewer);
7035 reflected[0] = normal[0]*2*d - viewer[0];
7036 reflected[1] = normal[1]*2*d - viewer[1];
7037 reflected[2] = normal[2]*2*d - viewer[2];
7038 // note: this is proportinal to viewer, so we can normalize later
7040 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7041 VectorNormalize(worldreflected);
7043 // note: this sphere map only uses world x and z!
7044 // so positive and negative y will LOOK THE SAME.
7045 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7046 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7049 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7050 rsurface.texcoordtexture2f_bufferobject = 0;
7051 rsurface.texcoordtexture2f_bufferoffset = 0;
7054 // the only tcmod that needs software vertex processing is turbulent, so
7055 // check for it here and apply the changes if needed
7056 // and we only support that as the first one
7057 // (handling a mixture of turbulent and other tcmods would be problematic
7058 // without punting it entirely to a software path)
7059 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7061 amplitude = rsurface.texture->tcmods[0].parms[1];
7062 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7063 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7065 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7066 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)
7068 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7069 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7072 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7073 rsurface.texcoordtexture2f_bufferobject = 0;
7074 rsurface.texcoordtexture2f_bufferoffset = 0;
7076 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7077 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7078 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7079 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7082 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7085 const msurface_t *surface = texturesurfacelist[0];
7086 const msurface_t *surface2;
7091 // TODO: lock all array ranges before render, rather than on each surface
7092 if (texturenumsurfaces == 1)
7094 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7095 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);
7097 else if (r_batchmode.integer == 2)
7099 #define MAXBATCHTRIANGLES 4096
7100 int batchtriangles = 0;
7101 int batchelements[MAXBATCHTRIANGLES*3];
7102 for (i = 0;i < texturenumsurfaces;i = j)
7104 surface = texturesurfacelist[i];
7106 if (surface->num_triangles > MAXBATCHTRIANGLES)
7108 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);
7111 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7112 batchtriangles = surface->num_triangles;
7113 firstvertex = surface->num_firstvertex;
7114 endvertex = surface->num_firstvertex + surface->num_vertices;
7115 for (;j < texturenumsurfaces;j++)
7117 surface2 = texturesurfacelist[j];
7118 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7120 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7121 batchtriangles += surface2->num_triangles;
7122 firstvertex = min(firstvertex, surface2->num_firstvertex);
7123 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7125 surface2 = texturesurfacelist[j-1];
7126 numvertices = endvertex - firstvertex;
7127 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7130 else if (r_batchmode.integer == 1)
7132 for (i = 0;i < texturenumsurfaces;i = j)
7134 surface = texturesurfacelist[i];
7135 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7136 if (texturesurfacelist[j] != surface2)
7138 surface2 = texturesurfacelist[j-1];
7139 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7140 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7141 GL_LockArrays(surface->num_firstvertex, numvertices);
7142 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7147 for (i = 0;i < texturenumsurfaces;i++)
7149 surface = texturesurfacelist[i];
7150 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7151 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);
7156 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
7158 int i, planeindex, vertexindex;
7162 r_waterstate_waterplane_t *p, *bestp;
7163 const msurface_t *surface;
7164 if (r_waterstate.renderingscene)
7166 for (i = 0;i < texturenumsurfaces;i++)
7168 surface = texturesurfacelist[i];
7169 if (lightmaptexunit >= 0)
7170 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7171 if (deluxemaptexunit >= 0)
7172 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7173 // pick the closest matching water plane
7176 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7179 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7181 Matrix4x4_Transform(&rsurface.matrix, v, vert);
7182 d += fabs(PlaneDiff(vert, &p->plane));
7184 if (bestd > d || !bestp)
7192 if (refractiontexunit >= 0)
7193 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
7194 if (reflectiontexunit >= 0)
7195 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
7199 if (refractiontexunit >= 0)
7200 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
7201 if (reflectiontexunit >= 0)
7202 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
7204 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7205 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);
7209 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
7213 const msurface_t *surface = texturesurfacelist[0];
7214 const msurface_t *surface2;
7219 // TODO: lock all array ranges before render, rather than on each surface
7220 if (texturenumsurfaces == 1)
7222 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7223 if (deluxemaptexunit >= 0)
7224 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7225 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7226 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);
7228 else if (r_batchmode.integer == 2)
7230 #define MAXBATCHTRIANGLES 4096
7231 int batchtriangles = 0;
7232 int batchelements[MAXBATCHTRIANGLES*3];
7233 for (i = 0;i < texturenumsurfaces;i = j)
7235 surface = texturesurfacelist[i];
7236 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7237 if (deluxemaptexunit >= 0)
7238 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7240 if (surface->num_triangles > MAXBATCHTRIANGLES)
7242 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);
7245 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7246 batchtriangles = surface->num_triangles;
7247 firstvertex = surface->num_firstvertex;
7248 endvertex = surface->num_firstvertex + surface->num_vertices;
7249 for (;j < texturenumsurfaces;j++)
7251 surface2 = texturesurfacelist[j];
7252 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7254 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7255 batchtriangles += surface2->num_triangles;
7256 firstvertex = min(firstvertex, surface2->num_firstvertex);
7257 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7259 surface2 = texturesurfacelist[j-1];
7260 numvertices = endvertex - firstvertex;
7261 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7264 else if (r_batchmode.integer == 1)
7267 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
7268 for (i = 0;i < texturenumsurfaces;i = j)
7270 surface = texturesurfacelist[i];
7271 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7272 if (texturesurfacelist[j] != surface2)
7274 Con_Printf(" %i", j - i);
7277 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
7279 for (i = 0;i < texturenumsurfaces;i = j)
7281 surface = texturesurfacelist[i];
7282 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7283 if (deluxemaptexunit >= 0)
7284 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7285 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7286 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
7289 Con_Printf(" %i", j - i);
7291 surface2 = texturesurfacelist[j-1];
7292 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7293 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7294 GL_LockArrays(surface->num_firstvertex, numvertices);
7295 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7303 for (i = 0;i < texturenumsurfaces;i++)
7305 surface = texturesurfacelist[i];
7306 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
7307 if (deluxemaptexunit >= 0)
7308 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7309 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7310 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7315 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7318 int texturesurfaceindex;
7319 if (r_showsurfaces.integer == 2)
7321 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7323 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7324 for (j = 0;j < surface->num_triangles;j++)
7326 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7327 GL_Color(f, f, f, 1);
7328 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7334 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7336 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7337 int k = (int)(((size_t)surface) / sizeof(msurface_t));
7338 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);
7339 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7340 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);
7345 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7347 int texturesurfaceindex;
7351 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7353 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7354 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)
7362 rsurface.lightmapcolor4f = rsurface.array_color4f;
7363 rsurface.lightmapcolor4f_bufferobject = 0;
7364 rsurface.lightmapcolor4f_bufferoffset = 0;
7367 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7369 int texturesurfaceindex;
7375 if (rsurface.lightmapcolor4f)
7377 // generate color arrays for the surfaces in this list
7378 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7380 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7381 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)
7383 f = RSurf_FogVertex(v);
7393 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7395 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7396 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)
7398 f = RSurf_FogVertex(v);
7406 rsurface.lightmapcolor4f = rsurface.array_color4f;
7407 rsurface.lightmapcolor4f_bufferobject = 0;
7408 rsurface.lightmapcolor4f_bufferoffset = 0;
7411 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7413 int texturesurfaceindex;
7419 if (!rsurface.lightmapcolor4f)
7421 // generate color arrays for the surfaces in this list
7422 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7424 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7425 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)
7427 f = RSurf_FogVertex(v);
7428 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7429 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7430 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7434 rsurface.lightmapcolor4f = rsurface.array_color4f;
7435 rsurface.lightmapcolor4f_bufferobject = 0;
7436 rsurface.lightmapcolor4f_bufferoffset = 0;
7439 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7441 int texturesurfaceindex;
7445 if (!rsurface.lightmapcolor4f)
7447 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7449 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7450 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)
7458 rsurface.lightmapcolor4f = rsurface.array_color4f;
7459 rsurface.lightmapcolor4f_bufferobject = 0;
7460 rsurface.lightmapcolor4f_bufferoffset = 0;
7463 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7465 int texturesurfaceindex;
7469 if (!rsurface.lightmapcolor4f)
7471 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7473 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7474 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)
7476 c2[0] = c[0] + r_refdef.scene.ambient;
7477 c2[1] = c[1] + r_refdef.scene.ambient;
7478 c2[2] = c[2] + r_refdef.scene.ambient;
7482 rsurface.lightmapcolor4f = rsurface.array_color4f;
7483 rsurface.lightmapcolor4f_bufferobject = 0;
7484 rsurface.lightmapcolor4f_bufferoffset = 0;
7487 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7490 rsurface.lightmapcolor4f = NULL;
7491 rsurface.lightmapcolor4f_bufferobject = 0;
7492 rsurface.lightmapcolor4f_bufferoffset = 0;
7493 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7494 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7495 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7496 GL_Color(r, g, b, a);
7497 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7500 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7502 // TODO: optimize applyfog && applycolor case
7503 // just apply fog if necessary, and tint the fog color array if necessary
7504 rsurface.lightmapcolor4f = NULL;
7505 rsurface.lightmapcolor4f_bufferobject = 0;
7506 rsurface.lightmapcolor4f_bufferoffset = 0;
7507 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7508 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7509 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7510 GL_Color(r, g, b, a);
7511 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7514 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7516 int texturesurfaceindex;
7520 if (texturesurfacelist[0]->lightmapinfo)
7522 // generate color arrays for the surfaces in this list
7523 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7525 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7526 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7528 if (surface->lightmapinfo->samples)
7530 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7531 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7532 VectorScale(lm, scale, c);
7533 if (surface->lightmapinfo->styles[1] != 255)
7535 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7537 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7538 VectorMA(c, scale, lm, c);
7539 if (surface->lightmapinfo->styles[2] != 255)
7542 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7543 VectorMA(c, scale, lm, c);
7544 if (surface->lightmapinfo->styles[3] != 255)
7547 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7548 VectorMA(c, scale, lm, c);
7558 rsurface.lightmapcolor4f = rsurface.array_color4f;
7559 rsurface.lightmapcolor4f_bufferobject = 0;
7560 rsurface.lightmapcolor4f_bufferoffset = 0;
7564 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7565 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7566 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7568 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7569 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7570 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7571 GL_Color(r, g, b, a);
7572 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7575 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7577 int texturesurfaceindex;
7584 vec3_t ambientcolor;
7585 vec3_t diffusecolor;
7589 VectorCopy(rsurface.modellight_lightdir, lightdir);
7590 f = 0.5f * r_refdef.lightmapintensity;
7591 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7592 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7593 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7594 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7595 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7596 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7598 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7600 // generate color arrays for the surfaces in this list
7601 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7603 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7604 int numverts = surface->num_vertices;
7605 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7606 n = rsurface.normal3f + 3 * surface->num_firstvertex;
7607 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7608 // q3-style directional shading
7609 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7611 if ((f = DotProduct(n, lightdir)) > 0)
7612 VectorMA(ambientcolor, f, diffusecolor, c);
7614 VectorCopy(ambientcolor, c);
7622 rsurface.lightmapcolor4f = rsurface.array_color4f;
7623 rsurface.lightmapcolor4f_bufferobject = 0;
7624 rsurface.lightmapcolor4f_bufferoffset = 0;
7625 *applycolor = false;
7629 *r = ambientcolor[0];
7630 *g = ambientcolor[1];
7631 *b = ambientcolor[2];
7632 rsurface.lightmapcolor4f = NULL;
7633 rsurface.lightmapcolor4f_bufferobject = 0;
7634 rsurface.lightmapcolor4f_bufferoffset = 0;
7638 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7640 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7641 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7642 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7643 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7644 GL_Color(r, g, b, a);
7645 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7648 void RSurf_SetupDepthAndCulling(void)
7650 // submodels are biased to avoid z-fighting with world surfaces that they
7651 // may be exactly overlapping (avoids z-fighting artifacts on certain
7652 // doors and things in Quake maps)
7653 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7654 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7655 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7656 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7659 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7661 // transparent sky would be ridiculous
7662 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7664 R_SetupGenericShader(false);
7665 skyrenderlater = true;
7666 RSurf_SetupDepthAndCulling();
7668 // LordHavoc: HalfLife maps have freaky skypolys so don't use
7669 // skymasking on them, and Quake3 never did sky masking (unlike
7670 // software Quake and software Quake2), so disable the sky masking
7671 // in Quake3 maps as it causes problems with q3map2 sky tricks,
7672 // and skymasking also looks very bad when noclipping outside the
7673 // level, so don't use it then either.
7674 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7676 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7677 R_Mesh_ColorPointer(NULL, 0, 0);
7678 R_Mesh_ResetTextureState();
7679 if (skyrendermasked)
7681 R_SetupDepthOrShadowShader();
7682 // depth-only (masking)
7683 GL_ColorMask(0,0,0,0);
7684 // just to make sure that braindead drivers don't draw
7685 // anything despite that colormask...
7686 GL_BlendFunc(GL_ZERO, GL_ONE);
7690 R_SetupGenericShader(false);
7692 GL_BlendFunc(GL_ONE, GL_ZERO);
7694 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7695 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7696 if (skyrendermasked)
7697 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7699 R_Mesh_ResetTextureState();
7700 GL_Color(1, 1, 1, 1);
7703 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
7704 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
7705 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
7707 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7710 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7711 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7712 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7713 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7714 if (rsurface.texture->backgroundcurrentskinframe)
7716 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7717 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7718 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7719 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7721 if (rsurface.texture->colormapping)
7723 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7724 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7726 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7727 if (r_shadow_usingdeferredprepass)
7729 R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture));
7730 R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR, 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture));
7732 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7733 R_Mesh_ColorPointer(NULL, 0, 0);
7735 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7737 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass)
7739 // render background
7740 GL_BlendFunc(GL_ONE, GL_ZERO);
7742 GL_AlphaTest(false);
7744 GL_Color(1, 1, 1, 1);
7745 R_Mesh_ColorPointer(NULL, 0, 0);
7747 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7748 if (r_glsl_permutation)
7750 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7751 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7752 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7753 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7754 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7755 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7756 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);
7758 GL_LockArrays(0, 0);
7760 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7761 GL_DepthMask(false);
7762 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7763 R_Mesh_ColorPointer(NULL, 0, 0);
7765 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7766 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7767 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7770 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
7771 if (!r_glsl_permutation)
7774 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7775 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7776 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7777 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7778 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7780 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7782 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7784 GL_BlendFunc(GL_ONE, GL_ZERO);
7786 GL_AlphaTest(false);
7790 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7791 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7792 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
7795 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7797 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7798 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);
7800 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7804 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7805 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);
7807 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7809 GL_LockArrays(0, 0);
7812 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7814 // OpenGL 1.3 path - anything not completely ancient
7815 int texturesurfaceindex;
7816 qboolean applycolor;
7819 const texturelayer_t *layer;
7820 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7822 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7825 int layertexrgbscale;
7826 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7828 if (layerindex == 0)
7832 GL_AlphaTest(false);
7833 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7836 GL_DepthMask(layer->depthmask && writedepth);
7837 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7838 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7840 layertexrgbscale = 4;
7841 VectorScale(layer->color, 0.25f, layercolor);
7843 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7845 layertexrgbscale = 2;
7846 VectorScale(layer->color, 0.5f, layercolor);
7850 layertexrgbscale = 1;
7851 VectorScale(layer->color, 1.0f, layercolor);
7853 layercolor[3] = layer->color[3];
7854 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7855 R_Mesh_ColorPointer(NULL, 0, 0);
7856 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
7857 switch (layer->type)
7859 case TEXTURELAYERTYPE_LITTEXTURE:
7860 // single-pass lightmapped texture with 2x rgbscale
7861 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
7862 R_Mesh_TexMatrix(0, NULL);
7863 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7864 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7865 R_Mesh_TexBind(1, R_GetTexture(layer->texture));
7866 R_Mesh_TexMatrix(1, &layer->texmatrix);
7867 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7868 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7869 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7870 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7871 else if (rsurface.uselightmaptexture)
7872 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7874 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7876 case TEXTURELAYERTYPE_TEXTURE:
7877 // singletexture unlit texture with transparency support
7878 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7879 R_Mesh_TexMatrix(0, &layer->texmatrix);
7880 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7881 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7882 R_Mesh_TexBind(1, 0);
7883 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
7884 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7886 case TEXTURELAYERTYPE_FOG:
7887 // singletexture fogging
7890 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7891 R_Mesh_TexMatrix(0, &layer->texmatrix);
7892 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
7893 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7897 R_Mesh_TexBind(0, 0);
7898 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
7900 R_Mesh_TexBind(1, 0);
7901 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
7902 // generate a color array for the fog pass
7903 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7904 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7910 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7911 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)
7913 f = 1 - RSurf_FogVertex(v);
7914 c[0] = layercolor[0];
7915 c[1] = layercolor[1];
7916 c[2] = layercolor[2];
7917 c[3] = f * layercolor[3];
7920 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7923 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7925 GL_LockArrays(0, 0);
7928 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7930 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7931 GL_AlphaTest(false);
7935 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7937 // OpenGL 1.1 - crusty old voodoo path
7938 int texturesurfaceindex;
7941 const texturelayer_t *layer;
7942 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7944 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7946 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7948 if (layerindex == 0)
7952 GL_AlphaTest(false);
7953 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7956 GL_DepthMask(layer->depthmask && writedepth);
7957 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7958 R_Mesh_ColorPointer(NULL, 0, 0);
7959 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
7960 switch (layer->type)
7962 case TEXTURELAYERTYPE_LITTEXTURE:
7963 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7965 // two-pass lit texture with 2x rgbscale
7966 // first the lightmap pass
7967 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
7968 R_Mesh_TexMatrix(0, NULL);
7969 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7970 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7971 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7972 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7973 else if (rsurface.uselightmaptexture)
7974 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7976 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7977 GL_LockArrays(0, 0);
7978 // then apply the texture to it
7979 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7980 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7981 R_Mesh_TexMatrix(0, &layer->texmatrix);
7982 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7983 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7984 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);
7988 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7989 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
7990 R_Mesh_TexMatrix(0, &layer->texmatrix);
7991 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
7992 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7993 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7994 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);
7996 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);
7999 case TEXTURELAYERTYPE_TEXTURE:
8000 // singletexture unlit texture with transparency support
8001 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8002 R_Mesh_TexMatrix(0, &layer->texmatrix);
8003 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8004 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8005 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);
8007 case TEXTURELAYERTYPE_FOG:
8008 // singletexture fogging
8011 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8012 R_Mesh_TexMatrix(0, &layer->texmatrix);
8013 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8014 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8018 R_Mesh_TexBind(0, 0);
8019 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8021 // generate a color array for the fog pass
8022 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8023 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8029 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8030 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)
8032 f = 1 - RSurf_FogVertex(v);
8033 c[0] = layer->color[0];
8034 c[1] = layer->color[1];
8035 c[2] = layer->color[2];
8036 c[3] = f * layer->color[3];
8039 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8042 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8044 GL_LockArrays(0, 0);
8047 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8049 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8050 GL_AlphaTest(false);
8054 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8058 GL_AlphaTest(false);
8059 R_Mesh_ColorPointer(NULL, 0, 0);
8060 R_Mesh_ResetTextureState();
8061 R_SetupGenericShader(false);
8063 if(rsurface.texture && rsurface.texture->currentskinframe)
8065 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8066 c[3] *= rsurface.texture->currentalpha;
8076 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
8078 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8079 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8080 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8083 // brighten it up (as texture value 127 means "unlit")
8084 c[0] *= 2 * r_refdef.view.colorscale;
8085 c[1] *= 2 * r_refdef.view.colorscale;
8086 c[2] *= 2 * r_refdef.view.colorscale;
8088 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8089 c[3] *= r_wateralpha.value;
8091 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8093 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8094 GL_DepthMask(false);
8096 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8098 GL_BlendFunc(GL_ONE, GL_ONE);
8099 GL_DepthMask(false);
8101 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8103 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8104 GL_DepthMask(false);
8106 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8108 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8109 GL_DepthMask(false);
8113 GL_BlendFunc(GL_ONE, GL_ZERO);
8114 GL_DepthMask(writedepth);
8117 rsurface.lightmapcolor4f = NULL;
8119 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8121 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8123 rsurface.lightmapcolor4f = NULL;
8124 rsurface.lightmapcolor4f_bufferobject = 0;
8125 rsurface.lightmapcolor4f_bufferoffset = 0;
8127 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8129 qboolean applycolor = true;
8132 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8134 r_refdef.lightmapintensity = 1;
8135 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8136 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8140 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8142 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8143 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8144 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8147 if(!rsurface.lightmapcolor4f)
8148 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8150 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8151 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8152 if(r_refdef.fogenabled)
8153 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8155 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8156 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8159 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8162 RSurf_SetupDepthAndCulling();
8163 if (r_showsurfaces.integer == 3 && !prepass)
8165 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8168 switch (vid.renderpath)
8170 case RENDERPATH_GL20:
8171 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8173 case RENDERPATH_GL13:
8174 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8176 case RENDERPATH_GL11:
8177 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8183 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8186 RSurf_SetupDepthAndCulling();
8187 if (r_showsurfaces.integer == 3 && !prepass)
8189 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8192 switch (vid.renderpath)
8194 case RENDERPATH_GL20:
8195 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8197 case RENDERPATH_GL13:
8198 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8200 case RENDERPATH_GL11:
8201 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8207 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8210 int texturenumsurfaces, endsurface;
8212 const msurface_t *surface;
8213 const msurface_t *texturesurfacelist[1024];
8215 // if the model is static it doesn't matter what value we give for
8216 // wantnormals and wanttangents, so this logic uses only rules applicable
8217 // to a model, knowing that they are meaningless otherwise
8218 if (ent == r_refdef.scene.worldentity)
8219 RSurf_ActiveWorldEntity();
8220 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8221 RSurf_ActiveModelEntity(ent, false, false, false);
8224 switch (vid.renderpath)
8226 case RENDERPATH_GL20:
8227 RSurf_ActiveModelEntity(ent, true, true, false);
8229 case RENDERPATH_GL13:
8230 case RENDERPATH_GL11:
8231 RSurf_ActiveModelEntity(ent, true, false, false);
8236 if (r_transparentdepthmasking.integer)
8238 qboolean setup = false;
8239 for (i = 0;i < numsurfaces;i = j)
8242 surface = rsurface.modelsurfaces + surfacelist[i];
8243 texture = surface->texture;
8244 rsurface.texture = R_GetCurrentTexture(texture);
8245 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8246 // scan ahead until we find a different texture
8247 endsurface = min(i + 1024, numsurfaces);
8248 texturenumsurfaces = 0;
8249 texturesurfacelist[texturenumsurfaces++] = surface;
8250 for (;j < endsurface;j++)
8252 surface = rsurface.modelsurfaces + surfacelist[j];
8253 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8255 texturesurfacelist[texturenumsurfaces++] = surface;
8257 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
8259 // render the range of surfaces as depth
8263 GL_ColorMask(0,0,0,0);
8266 GL_BlendFunc(GL_ONE, GL_ZERO);
8268 GL_AlphaTest(false);
8269 R_Mesh_ColorPointer(NULL, 0, 0);
8270 R_Mesh_ResetTextureState();
8271 R_SetupDepthOrShadowShader();
8273 RSurf_SetupDepthAndCulling();
8274 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8275 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8278 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8281 for (i = 0;i < numsurfaces;i = j)
8284 surface = rsurface.modelsurfaces + surfacelist[i];
8285 texture = surface->texture;
8286 rsurface.texture = R_GetCurrentTexture(texture);
8287 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
8288 // scan ahead until we find a different texture
8289 endsurface = min(i + 1024, numsurfaces);
8290 texturenumsurfaces = 0;
8291 texturesurfacelist[texturenumsurfaces++] = surface;
8292 for (;j < endsurface;j++)
8294 surface = rsurface.modelsurfaces + surfacelist[j];
8295 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
8297 texturesurfacelist[texturenumsurfaces++] = surface;
8299 // render the range of surfaces
8300 if (ent == r_refdef.scene.worldentity)
8301 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8303 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
8305 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8306 GL_AlphaTest(false);
8309 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
8311 // transparent surfaces get pushed off into the transparent queue
8312 int surfacelistindex;
8313 const msurface_t *surface;
8314 vec3_t tempcenter, center;
8315 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8317 surface = texturesurfacelist[surfacelistindex];
8318 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8319 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8320 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8321 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8322 if (queueentity->transparent_offset) // transparent offset
8324 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8325 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8326 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8328 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8332 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
8334 const entity_render_t *queueentity = r_refdef.scene.worldentity;
8338 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8340 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8342 RSurf_SetupDepthAndCulling();
8343 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8344 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8348 if (!rsurface.texture->currentnumlayers)
8350 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8351 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8353 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8355 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
8357 RSurf_SetupDepthAndCulling();
8358 GL_AlphaTest(false);
8359 R_Mesh_ColorPointer(NULL, 0, 0);
8360 R_Mesh_ResetTextureState();
8361 R_SetupGenericShader(false);
8362 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8364 GL_BlendFunc(GL_ONE, GL_ZERO);
8365 GL_Color(0, 0, 0, 1);
8366 GL_DepthTest(writedepth);
8367 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8369 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
8371 RSurf_SetupDepthAndCulling();
8372 GL_AlphaTest(false);
8373 R_Mesh_ColorPointer(NULL, 0, 0);
8374 R_Mesh_ResetTextureState();
8375 R_SetupGenericShader(false);
8376 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8378 GL_BlendFunc(GL_ONE, GL_ZERO);
8380 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8382 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8383 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8384 else if (!rsurface.texture->currentnumlayers)
8386 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8388 // in the deferred case, transparent surfaces were queued during prepass
8389 if (!r_shadow_usingdeferredprepass)
8390 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8394 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8395 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8400 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8404 // break the surface list down into batches by texture and use of lightmapping
8405 for (i = 0;i < numsurfaces;i = j)
8408 // texture is the base texture pointer, rsurface.texture is the
8409 // current frame/skin the texture is directing us to use (for example
8410 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8411 // use skin 1 instead)
8412 texture = surfacelist[i]->texture;
8413 rsurface.texture = R_GetCurrentTexture(texture);
8414 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8415 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8417 // if this texture is not the kind we want, skip ahead to the next one
8418 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8422 // simply scan ahead until we find a different texture or lightmap state
8423 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8425 // render the range of surfaces
8426 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
8430 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
8435 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8437 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8439 RSurf_SetupDepthAndCulling();
8440 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8441 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8445 if (!rsurface.texture->currentnumlayers)
8447 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8448 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8450 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8452 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8454 RSurf_SetupDepthAndCulling();
8455 GL_AlphaTest(false);
8456 R_Mesh_ColorPointer(NULL, 0, 0);
8457 R_Mesh_ResetTextureState();
8458 R_SetupGenericShader(false);
8459 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8461 GL_BlendFunc(GL_ONE, GL_ZERO);
8462 GL_Color(0, 0, 0, 1);
8463 GL_DepthTest(writedepth);
8464 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8466 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8468 RSurf_SetupDepthAndCulling();
8469 GL_AlphaTest(false);
8470 R_Mesh_ColorPointer(NULL, 0, 0);
8471 R_Mesh_ResetTextureState();
8472 R_SetupGenericShader(false);
8473 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8475 GL_BlendFunc(GL_ONE, GL_ZERO);
8477 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8479 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8480 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8481 else if (!rsurface.texture->currentnumlayers)
8483 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8485 // in the deferred case, transparent surfaces were queued during prepass
8486 if (!r_shadow_usingdeferredprepass)
8487 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
8491 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8492 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
8497 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
8501 // break the surface list down into batches by texture and use of lightmapping
8502 for (i = 0;i < numsurfaces;i = j)
8505 // texture is the base texture pointer, rsurface.texture is the
8506 // current frame/skin the texture is directing us to use (for example
8507 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8508 // use skin 1 instead)
8509 texture = surfacelist[i]->texture;
8510 rsurface.texture = R_GetCurrentTexture(texture);
8511 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
8512 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8514 // if this texture is not the kind we want, skip ahead to the next one
8515 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8519 // simply scan ahead until we find a different texture or lightmap state
8520 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8522 // render the range of surfaces
8523 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
8527 float locboxvertex3f[6*4*3] =
8529 1,0,1, 1,0,0, 1,1,0, 1,1,1,
8530 0,1,1, 0,1,0, 0,0,0, 0,0,1,
8531 1,1,1, 1,1,0, 0,1,0, 0,1,1,
8532 0,0,1, 0,0,0, 1,0,0, 1,0,1,
8533 0,0,1, 1,0,1, 1,1,1, 0,1,1,
8534 1,0,0, 0,0,0, 0,1,0, 1,1,0
8537 unsigned short locboxelements[6*2*3] =
8547 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8550 cl_locnode_t *loc = (cl_locnode_t *)ent;
8552 float vertex3f[6*4*3];
8554 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8555 GL_DepthMask(false);
8556 GL_DepthRange(0, 1);
8557 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8559 GL_CullFace(GL_NONE);
8560 R_Mesh_Matrix(&identitymatrix);
8562 R_Mesh_VertexPointer(vertex3f, 0, 0);
8563 R_Mesh_ColorPointer(NULL, 0, 0);
8564 R_Mesh_ResetTextureState();
8565 R_SetupGenericShader(false);
8568 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8569 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8570 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8571 surfacelist[0] < 0 ? 0.5f : 0.125f);
8573 if (VectorCompare(loc->mins, loc->maxs))
8575 VectorSet(size, 2, 2, 2);
8576 VectorMA(loc->mins, -0.5f, size, mins);
8580 VectorCopy(loc->mins, mins);
8581 VectorSubtract(loc->maxs, loc->mins, size);
8584 for (i = 0;i < 6*4*3;)
8585 for (j = 0;j < 3;j++, i++)
8586 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8588 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8591 void R_DrawLocs(void)
8594 cl_locnode_t *loc, *nearestloc;
8596 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8597 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8599 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8600 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8604 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8606 if (decalsystem->decals)
8607 Mem_Free(decalsystem->decals);
8608 memset(decalsystem, 0, sizeof(*decalsystem));
8611 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)
8618 // expand or initialize the system
8619 if (decalsystem->maxdecals <= decalsystem->numdecals)
8621 decalsystem_t old = *decalsystem;
8622 qboolean useshortelements;
8623 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8624 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8625 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)));
8626 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8627 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8628 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8629 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8630 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8631 if (decalsystem->numdecals)
8632 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8634 Mem_Free(old.decals);
8635 for (i = 0;i < decalsystem->maxdecals*3;i++)
8636 decalsystem->element3i[i] = i;
8637 if (useshortelements)
8638 for (i = 0;i < decalsystem->maxdecals*3;i++)
8639 decalsystem->element3s[i] = i;
8642 // grab a decal and search for another free slot for the next one
8643 maxdecals = decalsystem->maxdecals;
8644 decals = decalsystem->decals;
8645 decal = decalsystem->decals + (i = decalsystem->freedecal++);
8646 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
8648 decalsystem->freedecal = i;
8649 if (decalsystem->numdecals <= i)
8650 decalsystem->numdecals = i + 1;
8652 // initialize the decal
8654 decal->triangleindex = triangleindex;
8655 decal->surfaceindex = surfaceindex;
8656 decal->decalsequence = decalsequence;
8657 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
8658 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
8659 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
8660 decal->color4ub[0][3] = 255;
8661 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
8662 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
8663 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
8664 decal->color4ub[1][3] = 255;
8665 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
8666 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
8667 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
8668 decal->color4ub[2][3] = 255;
8669 decal->vertex3f[0][0] = v0[0];
8670 decal->vertex3f[0][1] = v0[1];
8671 decal->vertex3f[0][2] = v0[2];
8672 decal->vertex3f[1][0] = v1[0];
8673 decal->vertex3f[1][1] = v1[1];
8674 decal->vertex3f[1][2] = v1[2];
8675 decal->vertex3f[2][0] = v2[0];
8676 decal->vertex3f[2][1] = v2[1];
8677 decal->vertex3f[2][2] = v2[2];
8678 decal->texcoord2f[0][0] = t0[0];
8679 decal->texcoord2f[0][1] = t0[1];
8680 decal->texcoord2f[1][0] = t1[0];
8681 decal->texcoord2f[1][1] = t1[1];
8682 decal->texcoord2f[2][0] = t2[0];
8683 decal->texcoord2f[2][1] = t2[1];
8686 extern cvar_t cl_decals_bias;
8687 extern cvar_t cl_decals_models;
8688 extern cvar_t cl_decals_newsystem_intensitymultiplier;
8689 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)
8691 matrix4x4_t projection;
8692 decalsystem_t *decalsystem;
8695 const float *vertex3f;
8696 const msurface_t *surface;
8697 const msurface_t *surfaces;
8698 const int *surfacelist;
8699 const texture_t *texture;
8703 int surfacelistindex;
8706 int decalsurfaceindex;
8711 float localorigin[3];
8712 float localnormal[3];
8723 float points[2][9][3];
8727 decalsystem = &ent->decalsystem;
8729 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8731 R_DecalSystem_Reset(&ent->decalsystem);
8735 if (!model->brush.data_nodes && !cl_decals_models.integer)
8737 if (decalsystem->model)
8738 R_DecalSystem_Reset(decalsystem);
8742 if (decalsystem->model != model)
8743 R_DecalSystem_Reset(decalsystem);
8744 decalsystem->model = model;
8746 RSurf_ActiveModelEntity(ent, false, false, false);
8748 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8749 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8750 VectorNormalize(localnormal);
8751 localsize = worldsize*rsurface.inversematrixscale;
8752 ilocalsize = 1.0f / localsize;
8753 localmins[0] = localorigin[0] - localsize;
8754 localmins[1] = localorigin[1] - localsize;
8755 localmins[2] = localorigin[2] - localsize;
8756 localmaxs[0] = localorigin[0] + localsize;
8757 localmaxs[1] = localorigin[1] + localsize;
8758 localmaxs[2] = localorigin[2] + localsize;
8760 //VectorCopy(localnormal, planes[4]);
8761 //VectorVectors(planes[4], planes[2], planes[0]);
8762 AnglesFromVectors(angles, localnormal, NULL, false);
8763 AngleVectors(angles, planes[0], planes[2], planes[4]);
8764 VectorNegate(planes[0], planes[1]);
8765 VectorNegate(planes[2], planes[3]);
8766 VectorNegate(planes[4], planes[5]);
8767 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8768 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8769 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8770 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8771 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8772 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8777 matrix4x4_t forwardprojection;
8778 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8779 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8784 float projectionvector[4][3];
8785 VectorScale(planes[0], ilocalsize, projectionvector[0]);
8786 VectorScale(planes[2], ilocalsize, projectionvector[1]);
8787 VectorScale(planes[4], ilocalsize, projectionvector[2]);
8788 projectionvector[0][0] = planes[0][0] * ilocalsize;
8789 projectionvector[0][1] = planes[1][0] * ilocalsize;
8790 projectionvector[0][2] = planes[2][0] * ilocalsize;
8791 projectionvector[1][0] = planes[0][1] * ilocalsize;
8792 projectionvector[1][1] = planes[1][1] * ilocalsize;
8793 projectionvector[1][2] = planes[2][1] * ilocalsize;
8794 projectionvector[2][0] = planes[0][2] * ilocalsize;
8795 projectionvector[2][1] = planes[1][2] * ilocalsize;
8796 projectionvector[2][2] = planes[2][2] * ilocalsize;
8797 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8798 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8799 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8800 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8804 dynamic = model->surfmesh.isanimated;
8805 vertex3f = rsurface.modelvertex3f;
8806 numsurfacelist = model->nummodelsurfaces;
8807 surfacelist = model->sortedmodelsurfaces;
8808 surfaces = model->data_surfaces;
8809 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8811 surfaceindex = surfacelist[surfacelistindex];
8812 surface = surfaces + surfaceindex;
8813 // skip transparent surfaces
8814 texture = surface->texture;
8815 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8817 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8819 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8821 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
8822 numvertices = surface->num_vertices;
8823 numtriangles = surface->num_triangles;
8824 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8826 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8828 index = 3*e[cornerindex];
8829 VectorCopy(vertex3f + index, v[cornerindex]);
8832 //TriangleNormal(v[0], v[1], v[2], normal);
8833 //if (DotProduct(normal, localnormal) < 0.0f)
8835 // clip by each of the box planes formed from the projection matrix
8836 // if anything survives, we emit the decal
8837 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]);
8840 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]);
8843 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]);
8846 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]);
8849 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]);
8852 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]);
8855 // some part of the triangle survived, so we have to accept it...
8858 // dynamic always uses the original triangle
8860 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8862 index = 3*e[cornerindex];
8863 VectorCopy(vertex3f + index, v[cornerindex]);
8866 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8868 // convert vertex positions to texcoords
8869 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8870 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8871 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8872 // calculate distance fade from the projection origin
8873 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
8874 f = bound(0.0f, f, 1.0f);
8875 c[cornerindex][0] = r * f;
8876 c[cornerindex][1] = g * f;
8877 c[cornerindex][2] = b * f;
8878 c[cornerindex][3] = 1.0f;
8879 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8882 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);
8884 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8885 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);
8890 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
8891 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)
8893 int renderentityindex;
8896 entity_render_t *ent;
8898 if (!cl_decals_newsystem.integer)
8901 worldmins[0] = worldorigin[0] - worldsize;
8902 worldmins[1] = worldorigin[1] - worldsize;
8903 worldmins[2] = worldorigin[2] - worldsize;
8904 worldmaxs[0] = worldorigin[0] + worldsize;
8905 worldmaxs[1] = worldorigin[1] + worldsize;
8906 worldmaxs[2] = worldorigin[2] + worldsize;
8908 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8910 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8912 ent = r_refdef.scene.entities[renderentityindex];
8913 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8916 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
8920 typedef struct r_decalsystem_splatqueue_s
8929 r_decalsystem_splatqueue_t;
8931 int r_decalsystem_numqueued = 0;
8932 #define MAX_DECALSYSTEM_QUEUE 1024
8933 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
8935 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)
8937 r_decalsystem_splatqueue_t *queue;
8939 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
8942 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
8943 VectorCopy(worldorigin, queue->worldorigin);
8944 VectorCopy(worldnormal, queue->worldnormal);
8945 Vector4Set(queue->color, r, g, b, a);
8946 Vector4Set(queue->tcrange, s1, t1, s2, t2);
8947 queue->worldsize = worldsize;
8948 queue->decalsequence = cl.decalsequence++;
8951 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
8954 r_decalsystem_splatqueue_t *queue;
8956 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
8957 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);
8958 r_decalsystem_numqueued = 0;
8961 extern cvar_t cl_decals_max;
8962 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
8965 decalsystem_t *decalsystem = &ent->decalsystem;
8972 if (!decalsystem->numdecals)
8975 if (r_showsurfaces.integer)
8978 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8980 R_DecalSystem_Reset(decalsystem);
8984 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
8985 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
8987 if (decalsystem->lastupdatetime)
8988 frametime = (cl.time - decalsystem->lastupdatetime);
8991 decalsystem->lastupdatetime = cl.time;
8992 decal = decalsystem->decals;
8993 numdecals = decalsystem->numdecals;
8995 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8997 if (decal->color4ub[0][3])
8999 decal->lived += frametime;
9000 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
9002 memset(decal, 0, sizeof(*decal));
9003 if (decalsystem->freedecal > i)
9004 decalsystem->freedecal = i;
9008 decal = decalsystem->decals;
9009 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
9012 // collapse the array by shuffling the tail decals into the gaps
9015 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
9016 decalsystem->freedecal++;
9017 if (decalsystem->freedecal == numdecals)
9019 decal[decalsystem->freedecal] = decal[--numdecals];
9022 decalsystem->numdecals = numdecals;
9026 // if there are no decals left, reset decalsystem
9027 R_DecalSystem_Reset(decalsystem);
9031 extern skinframe_t *decalskinframe;
9032 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9035 decalsystem_t *decalsystem = &ent->decalsystem;
9045 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9048 numdecals = decalsystem->numdecals;
9052 if (r_showsurfaces.integer)
9055 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9057 R_DecalSystem_Reset(decalsystem);
9061 // if the model is static it doesn't matter what value we give for
9062 // wantnormals and wanttangents, so this logic uses only rules applicable
9063 // to a model, knowing that they are meaningless otherwise
9064 if (ent == r_refdef.scene.worldentity)
9065 RSurf_ActiveWorldEntity();
9067 RSurf_ActiveModelEntity(ent, false, false, false);
9069 decalsystem->lastupdatetime = cl.time;
9070 decal = decalsystem->decals;
9072 fadedelay = cl_decals_time.value;
9073 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9075 // update vertex positions for animated models
9076 v3f = decalsystem->vertex3f;
9077 c4f = decalsystem->color4f;
9078 t2f = decalsystem->texcoord2f;
9079 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9081 if (!decal->color4ub[0][3])
9084 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9087 // update color values for fading decals
9088 if (decal->lived >= cl_decals_time.value)
9090 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9091 alpha *= (1.0f/255.0f);
9094 alpha = 1.0f/255.0f;
9096 c4f[ 0] = decal->color4ub[0][0] * alpha;
9097 c4f[ 1] = decal->color4ub[0][1] * alpha;
9098 c4f[ 2] = decal->color4ub[0][2] * alpha;
9100 c4f[ 4] = decal->color4ub[1][0] * alpha;
9101 c4f[ 5] = decal->color4ub[1][1] * alpha;
9102 c4f[ 6] = decal->color4ub[1][2] * alpha;
9104 c4f[ 8] = decal->color4ub[2][0] * alpha;
9105 c4f[ 9] = decal->color4ub[2][1] * alpha;
9106 c4f[10] = decal->color4ub[2][2] * alpha;
9109 t2f[0] = decal->texcoord2f[0][0];
9110 t2f[1] = decal->texcoord2f[0][1];
9111 t2f[2] = decal->texcoord2f[1][0];
9112 t2f[3] = decal->texcoord2f[1][1];
9113 t2f[4] = decal->texcoord2f[2][0];
9114 t2f[5] = decal->texcoord2f[2][1];
9116 // update vertex positions for animated models
9117 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9119 e = rsurface.modelelement3i + 3*decal->triangleindex;
9120 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9121 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9122 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9126 VectorCopy(decal->vertex3f[0], v3f);
9127 VectorCopy(decal->vertex3f[1], v3f + 3);
9128 VectorCopy(decal->vertex3f[2], v3f + 6);
9139 r_refdef.stats.drawndecals += numtris;
9141 if (r_refdef.fogenabled)
9143 switch(vid.renderpath)
9145 case RENDERPATH_GL20:
9146 case RENDERPATH_GL13:
9147 case RENDERPATH_GL11:
9148 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
9150 alpha = RSurf_FogVertex(v3f);
9159 // now render the decals all at once
9160 // (this assumes they all use one particle font texture!)
9161 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);
9162 R_Mesh_ResetTextureState();
9163 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9164 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9165 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9166 R_SetupGenericShader(true);
9167 GL_DepthMask(false);
9168 GL_DepthRange(0, 1);
9169 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9171 GL_CullFace(GL_NONE);
9172 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9173 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
9174 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
9175 GL_LockArrays(0, numtris * 3);
9176 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9177 GL_LockArrays(0, 0);
9181 static void R_DrawModelDecals(void)
9185 // fade faster when there are too many decals
9186 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9187 for (i = 0;i < r_refdef.scene.numentities;i++)
9188 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9190 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9191 for (i = 0;i < r_refdef.scene.numentities;i++)
9192 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9193 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9195 R_DecalSystem_ApplySplatEntitiesQueue();
9197 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9198 for (i = 0;i < r_refdef.scene.numentities;i++)
9199 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9201 r_refdef.stats.totaldecals += numdecals;
9203 if (r_showsurfaces.integer)
9206 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9208 for (i = 0;i < r_refdef.scene.numentities;i++)
9210 if (!r_refdef.viewcache.entityvisible[i])
9212 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9213 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
9217 void R_DrawDebugModel(void)
9219 entity_render_t *ent = rsurface.entity;
9220 int i, j, k, l, flagsmask;
9221 const int *elements;
9223 const msurface_t *surface;
9224 dp_model_t *model = ent->model;
9227 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
9229 R_Mesh_ColorPointer(NULL, 0, 0);
9230 R_Mesh_ResetTextureState();
9231 R_SetupGenericShader(false);
9232 GL_DepthRange(0, 1);
9233 GL_DepthTest(!r_showdisabledepthtest.integer);
9234 GL_DepthMask(false);
9235 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9237 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
9239 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
9240 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
9242 if (brush->colbrushf && brush->colbrushf->numtriangles)
9244 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
9245 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);
9246 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
9249 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
9251 if (surface->num_collisiontriangles)
9253 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
9254 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);
9255 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
9260 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9262 if (r_showtris.integer || r_shownormals.integer)
9264 if (r_showdisabledepthtest.integer)
9266 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9267 GL_DepthMask(false);
9271 GL_BlendFunc(GL_ONE, GL_ZERO);
9274 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
9276 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
9278 rsurface.texture = R_GetCurrentTexture(surface->texture);
9279 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
9281 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
9282 if (r_showtris.value > 0)
9284 if (!rsurface.texture->currentlayers->depthmask)
9285 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
9286 else if (ent == r_refdef.scene.worldentity)
9287 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
9289 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
9290 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
9291 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
9292 R_Mesh_ColorPointer(NULL, 0, 0);
9293 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
9294 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9295 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
9296 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);
9297 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9300 if (r_shownormals.value < 0)
9303 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9305 VectorCopy(rsurface.vertex3f + l * 3, v);
9306 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9307 qglVertex3f(v[0], v[1], v[2]);
9308 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
9309 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9310 qglVertex3f(v[0], v[1], v[2]);
9315 if (r_shownormals.value > 0)
9318 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9320 VectorCopy(rsurface.vertex3f + l * 3, v);
9321 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
9322 qglVertex3f(v[0], v[1], v[2]);
9323 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
9324 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9325 qglVertex3f(v[0], v[1], v[2]);
9330 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9332 VectorCopy(rsurface.vertex3f + l * 3, v);
9333 GL_Color(0, r_refdef.view.colorscale, 0, 1);
9334 qglVertex3f(v[0], v[1], v[2]);
9335 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
9336 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9337 qglVertex3f(v[0], v[1], v[2]);
9342 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
9344 VectorCopy(rsurface.vertex3f + l * 3, v);
9345 GL_Color(0, 0, r_refdef.view.colorscale, 1);
9346 qglVertex3f(v[0], v[1], v[2]);
9347 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
9348 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
9349 qglVertex3f(v[0], v[1], v[2]);
9356 rsurface.texture = NULL;
9360 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
9361 int r_maxsurfacelist = 0;
9362 const msurface_t **r_surfacelist = NULL;
9363 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9365 int i, j, endj, f, flagsmask;
9367 dp_model_t *model = r_refdef.scene.worldmodel;
9368 msurface_t *surfaces;
9369 unsigned char *update;
9370 int numsurfacelist = 0;
9374 if (r_maxsurfacelist < model->num_surfaces)
9376 r_maxsurfacelist = model->num_surfaces;
9378 Mem_Free((msurface_t**)r_surfacelist);
9379 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9382 RSurf_ActiveWorldEntity();
9384 surfaces = model->data_surfaces;
9385 update = model->brushq1.lightmapupdateflags;
9387 // update light styles on this submodel
9388 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9390 model_brush_lightstyleinfo_t *style;
9391 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9393 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9395 int *list = style->surfacelist;
9396 style->value = r_refdef.scene.lightstylevalue[style->style];
9397 for (j = 0;j < style->numsurfaces;j++)
9398 update[list[j]] = true;
9403 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9408 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9414 rsurface.uselightmaptexture = false;
9415 rsurface.texture = NULL;
9416 rsurface.rtlight = NULL;
9418 // add visible surfaces to draw list
9419 for (i = 0;i < model->nummodelsurfaces;i++)
9421 j = model->sortedmodelsurfaces[i];
9422 if (r_refdef.viewcache.world_surfacevisible[j])
9423 r_surfacelist[numsurfacelist++] = surfaces + j;
9425 // update lightmaps if needed
9427 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9428 if (r_refdef.viewcache.world_surfacevisible[j])
9430 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
9431 // don't do anything if there were no surfaces
9432 if (!numsurfacelist)
9434 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9437 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9438 GL_AlphaTest(false);
9440 // add to stats if desired
9441 if (r_speeds.integer && !skysurfaces && !depthonly)
9443 r_refdef.stats.world_surfaces += numsurfacelist;
9444 for (j = 0;j < numsurfacelist;j++)
9445 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
9448 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9451 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
9453 int i, j, endj, f, flagsmask;
9455 dp_model_t *model = ent->model;
9456 msurface_t *surfaces;
9457 unsigned char *update;
9458 int numsurfacelist = 0;
9462 if (r_maxsurfacelist < model->num_surfaces)
9464 r_maxsurfacelist = model->num_surfaces;
9466 Mem_Free((msurface_t **)r_surfacelist);
9467 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
9470 // if the model is static it doesn't matter what value we give for
9471 // wantnormals and wanttangents, so this logic uses only rules applicable
9472 // to a model, knowing that they are meaningless otherwise
9473 if (ent == r_refdef.scene.worldentity)
9474 RSurf_ActiveWorldEntity();
9475 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9476 RSurf_ActiveModelEntity(ent, false, false, false);
9478 RSurf_ActiveModelEntity(ent, true, true, true);
9480 RSurf_ActiveModelEntity(ent, false, false, false);
9483 switch (vid.renderpath)
9485 case RENDERPATH_GL20:
9486 RSurf_ActiveModelEntity(ent, true, true, false);
9488 case RENDERPATH_GL13:
9489 case RENDERPATH_GL11:
9490 RSurf_ActiveModelEntity(ent, true, false, false);
9495 surfaces = model->data_surfaces;
9496 update = model->brushq1.lightmapupdateflags;
9498 // update light styles
9499 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
9501 model_brush_lightstyleinfo_t *style;
9502 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
9504 if (style->value != r_refdef.scene.lightstylevalue[style->style])
9506 int *list = style->surfacelist;
9507 style->value = r_refdef.scene.lightstylevalue[style->style];
9508 for (j = 0;j < style->numsurfaces;j++)
9509 update[list[j]] = true;
9514 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
9519 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9525 rsurface.uselightmaptexture = false;
9526 rsurface.texture = NULL;
9527 rsurface.rtlight = NULL;
9529 // add visible surfaces to draw list
9530 for (i = 0;i < model->nummodelsurfaces;i++)
9531 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
9532 // don't do anything if there were no surfaces
9533 if (!numsurfacelist)
9535 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9538 // update lightmaps if needed
9540 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
9542 R_BuildLightMap(ent, surfaces + j);
9543 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
9544 GL_AlphaTest(false);
9546 // add to stats if desired
9547 if (r_speeds.integer && !skysurfaces && !depthonly)
9549 r_refdef.stats.entities_surfaces += numsurfacelist;
9550 for (j = 0;j < numsurfacelist;j++)
9551 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
9554 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9557 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
9559 static texture_t texture;
9560 static msurface_t surface;
9561 const msurface_t *surfacelist = &surface;
9563 // fake enough texture and surface state to render this geometry
9565 texture.update_lastrenderframe = -1; // regenerate this texture
9566 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9567 texture.currentskinframe = skinframe;
9568 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9569 texture.specularscalemod = 1;
9570 texture.specularpowermod = 1;
9572 surface.texture = &texture;
9573 surface.num_triangles = numtriangles;
9574 surface.num_firsttriangle = firsttriangle;
9575 surface.num_vertices = numvertices;
9576 surface.num_firstvertex = firstvertex;
9579 rsurface.texture = R_GetCurrentTexture(surface.texture);
9580 rsurface.uselightmaptexture = false;
9581 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
9584 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)
9586 static msurface_t surface;
9587 const msurface_t *surfacelist = &surface;
9589 // fake enough texture and surface state to render this geometry
9591 surface.texture = texture;
9592 surface.num_triangles = numtriangles;
9593 surface.num_firsttriangle = firsttriangle;
9594 surface.num_vertices = numvertices;
9595 surface.num_firstvertex = firstvertex;
9598 rsurface.texture = R_GetCurrentTexture(surface.texture);
9599 rsurface.uselightmaptexture = false;
9600 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);