2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
33 qboolean r_loadnormalmap;
42 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
43 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
44 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
45 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
46 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
47 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
48 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
49 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
51 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
52 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
53 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
54 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
55 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
57 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
58 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
59 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
60 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
61 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
62 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
63 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
64 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
65 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
66 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
67 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
68 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
69 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
70 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
71 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
72 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
73 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
74 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
75 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
76 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
77 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
78 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
79 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
80 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
81 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
82 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
83 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
84 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
85 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
86 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
87 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
88 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
89 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
90 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
91 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
92 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
93 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
94 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
95 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
96 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
97 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
98 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
100 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
101 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
102 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
103 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
104 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
105 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
106 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
107 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
109 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
110 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
111 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
113 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
114 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
115 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
116 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
117 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
118 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
119 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
120 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
121 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
123 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
124 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
125 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
126 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
127 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
129 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
130 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
131 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
132 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
134 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
135 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
136 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
137 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
138 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
139 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
140 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
142 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
143 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
144 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
145 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
147 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
149 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
151 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
153 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
154 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
155 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
156 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
157 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
158 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
159 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
161 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
163 extern cvar_t v_glslgamma;
165 extern qboolean v_flipped_state;
167 static struct r_bloomstate_s
172 int bloomwidth, bloomheight;
174 int screentexturewidth, screentextureheight;
175 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
177 int bloomtexturewidth, bloomtextureheight;
178 rtexture_t *texture_bloom;
180 // arrays for rendering the screen passes
181 float screentexcoord2f[8];
182 float bloomtexcoord2f[8];
183 float offsettexcoord2f[8];
185 r_viewport_t viewport;
189 r_waterstate_t r_waterstate;
191 /// shadow volume bsp struct with automatically growing nodes buffer
194 rtexture_t *r_texture_blanknormalmap;
195 rtexture_t *r_texture_white;
196 rtexture_t *r_texture_grey128;
197 rtexture_t *r_texture_black;
198 rtexture_t *r_texture_notexture;
199 rtexture_t *r_texture_whitecube;
200 rtexture_t *r_texture_normalizationcube;
201 rtexture_t *r_texture_fogattenuation;
202 rtexture_t *r_texture_gammaramps;
203 unsigned int r_texture_gammaramps_serial;
204 //rtexture_t *r_texture_fogintensity;
206 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
207 unsigned int r_numqueries;
208 unsigned int r_maxqueries;
210 typedef struct r_qwskincache_s
212 char name[MAX_QPATH];
213 skinframe_t *skinframe;
217 static r_qwskincache_t *r_qwskincache;
218 static int r_qwskincache_size;
220 /// vertex coordinates for a quad that covers the screen exactly
221 const float r_screenvertex3f[12] =
229 extern void R_DrawModelShadows(void);
231 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
234 for (i = 0;i < verts;i++)
245 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
248 for (i = 0;i < verts;i++)
258 // FIXME: move this to client?
261 if (gamemode == GAME_NEHAHRA)
263 Cvar_Set("gl_fogenable", "0");
264 Cvar_Set("gl_fogdensity", "0.2");
265 Cvar_Set("gl_fogred", "0.3");
266 Cvar_Set("gl_foggreen", "0.3");
267 Cvar_Set("gl_fogblue", "0.3");
269 r_refdef.fog_density = 0;
270 r_refdef.fog_red = 0;
271 r_refdef.fog_green = 0;
272 r_refdef.fog_blue = 0;
273 r_refdef.fog_alpha = 1;
274 r_refdef.fog_start = 0;
275 r_refdef.fog_end = 16384;
276 r_refdef.fog_height = 1<<30;
277 r_refdef.fog_fadedepth = 128;
280 static void R_BuildBlankTextures(void)
282 unsigned char data[4];
283 data[2] = 128; // normal X
284 data[1] = 128; // normal Y
285 data[0] = 255; // normal Z
286 data[3] = 128; // height
287 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
292 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
297 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
302 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
305 static void R_BuildNoTexture(void)
308 unsigned char pix[16][16][4];
309 // this makes a light grey/dark grey checkerboard texture
310 for (y = 0;y < 16;y++)
312 for (x = 0;x < 16;x++)
314 if ((y < 8) ^ (x < 8))
330 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
333 static void R_BuildWhiteCube(void)
335 unsigned char data[6*1*1*4];
336 memset(data, 255, sizeof(data));
337 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
340 static void R_BuildNormalizationCube(void)
344 vec_t s, t, intensity;
347 data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
348 for (side = 0;side < 6;side++)
350 for (y = 0;y < NORMSIZE;y++)
352 for (x = 0;x < NORMSIZE;x++)
354 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
355 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
390 intensity = 127.0f / sqrt(DotProduct(v, v));
391 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
392 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
393 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
394 data[((side*64+y)*64+x)*4+3] = 255;
398 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
402 static void R_BuildFogTexture(void)
406 unsigned char data1[FOGWIDTH][4];
407 //unsigned char data2[FOGWIDTH][4];
410 r_refdef.fogmasktable_start = r_refdef.fog_start;
411 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
412 r_refdef.fogmasktable_range = r_refdef.fogrange;
413 r_refdef.fogmasktable_density = r_refdef.fog_density;
415 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
416 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
418 d = (x * r - r_refdef.fogmasktable_start);
419 if(developer.integer >= 100)
420 Con_Printf("%f ", d);
422 if (r_fog_exp2.integer)
423 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
425 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
426 if(developer.integer >= 100)
427 Con_Printf(" : %f ", alpha);
428 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
429 if(developer.integer >= 100)
430 Con_Printf(" = %f\n", alpha);
431 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
434 for (x = 0;x < FOGWIDTH;x++)
436 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
441 //data2[x][0] = 255 - b;
442 //data2[x][1] = 255 - b;
443 //data2[x][2] = 255 - b;
446 if (r_texture_fogattenuation)
448 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
449 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
453 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
454 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
458 static const char *builtinshaderstring =
459 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
460 "// written by Forest 'LordHavoc' Hale\n"
462 "// enable various extensions depending on permutation:\n"
464 "#ifdef VERTEX_SHADER\n"
465 "uniform mat4 ModelViewProjectionMatrix;\n"
468 "#ifdef MODE_DEPTH_OR_SHADOW\n"
469 "#ifdef VERTEX_SHADER\n"
472 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
475 "#else // !MODE_DEPTH_ORSHADOW\n"
476 "#ifdef MODE_SHOWDEPTH\n"
477 "#ifdef VERTEX_SHADER\n"
480 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
481 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
485 "#ifdef FRAGMENT_SHADER\n"
488 " gl_FragColor = gl_Color;\n"
491 "#else // !MODE_SHOWDEPTH\n"
492 "#ifdef MODE_POSTPROCESS\n"
493 "varying vec2 TexCoord1;\n"
494 "varying vec2 TexCoord2;\n"
496 "#ifdef VERTEX_SHADER\n"
499 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
500 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
502 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
507 "#ifdef FRAGMENT_SHADER\n"
508 "uniform sampler2D Texture_First;\n"
510 "uniform sampler2D Texture_Second;\n"
512 "#ifdef USEGAMMARAMPS\n"
513 "uniform sampler2D Texture_GammaRamps;\n"
515 "#ifdef USESATURATION\n"
516 "uniform float Saturation;\n"
518 "#ifdef USEVIEWTINT\n"
519 "uniform vec4 ViewTintColor;\n"
521 "//uncomment these if you want to use them:\n"
522 "uniform vec4 UserVec1;\n"
523 "// uniform vec4 UserVec2;\n"
524 "// uniform vec4 UserVec3;\n"
525 "// uniform vec4 UserVec4;\n"
526 "// uniform float ClientTime;\n"
527 "uniform vec2 PixelSize;\n"
530 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
532 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
534 "#ifdef USEVIEWTINT\n"
535 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
538 "#ifdef USEPOSTPROCESSING\n"
539 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
540 "// 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"
541 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
542 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
543 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
544 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
545 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
546 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
549 "#ifdef USESATURATION\n"
550 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
551 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
552 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
553 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
556 "#ifdef USEGAMMARAMPS\n"
557 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
558 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
559 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
563 "#else // !MODE_POSTPROCESS\n"
564 "#ifdef MODE_GENERIC\n"
565 "#ifdef USEDIFFUSE\n"
566 "varying vec2 TexCoord1;\n"
568 "#ifdef USESPECULAR\n"
569 "varying vec2 TexCoord2;\n"
571 "#ifdef VERTEX_SHADER\n"
574 " gl_FrontColor = gl_Color;\n"
575 "#ifdef USEDIFFUSE\n"
576 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
578 "#ifdef USESPECULAR\n"
579 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
581 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
585 "#ifdef FRAGMENT_SHADER\n"
586 "#ifdef USEDIFFUSE\n"
587 "uniform sampler2D Texture_First;\n"
589 "#ifdef USESPECULAR\n"
590 "uniform sampler2D Texture_Second;\n"
595 " gl_FragColor = gl_Color;\n"
596 "#ifdef USEDIFFUSE\n"
597 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
600 "#ifdef USESPECULAR\n"
601 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
602 "# ifdef USECOLORMAPPING\n"
603 " gl_FragColor *= tex2;\n"
606 " gl_FragColor += tex2;\n"
608 "# ifdef USEVERTEXTEXTUREBLEND\n"
609 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
614 "#else // !MODE_GENERIC\n"
615 "#ifdef MODE_BLOOMBLUR\n"
616 "varying TexCoord;\n"
617 "#ifdef VERTEX_SHADER\n"
620 " gl_FrontColor = gl_Color;\n"
621 " TexCoord = gl_MultiTexCoord0.xy;\n"
622 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
626 "#ifdef FRAGMENT_SHADER\n"
627 "uniform sampler2D Texture_First;\n"
628 "uniform vec4 BloomBlur_Parameters;\n"
633 " vec2 tc = TexCoord;\n"
634 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
635 " tc += BloomBlur_Parameters.xy;\n"
636 " for (i = 1;i < SAMPLES;i++)\n"
638 " color += texture2D(Texture_First, tc).rgb;\n"
639 " tc += BloomBlur_Parameters.xy;\n"
641 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
644 "#else // !MODE_BLOOMBLUR\n"
645 "#ifdef MODE_REFRACTION\n"
646 "varying vec2 TexCoord;\n"
647 "varying vec4 ModelViewProjectionPosition;\n"
648 "uniform mat4 TexMatrix;\n"
649 "#ifdef VERTEX_SHADER\n"
653 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
654 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
655 " ModelViewProjectionPosition = gl_Position;\n"
659 "#ifdef FRAGMENT_SHADER\n"
660 "uniform sampler2D Texture_Normal;\n"
661 "uniform sampler2D Texture_Refraction;\n"
662 "uniform sampler2D Texture_Reflection;\n"
664 "uniform vec4 DistortScaleRefractReflect;\n"
665 "uniform vec4 ScreenScaleRefractReflect;\n"
666 "uniform vec4 ScreenCenterRefractReflect;\n"
667 "uniform vec4 RefractColor;\n"
668 "uniform vec4 ReflectColor;\n"
669 "uniform float ReflectFactor;\n"
670 "uniform float ReflectOffset;\n"
674 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
675 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
676 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
677 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
678 " // FIXME temporary hack to detect the case that the reflection\n"
679 " // gets blackened at edges due to leaving the area that contains actual\n"
681 " // Remove this 'ack once we have a better way to stop this thing from\n"
683 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
684 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
685 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
686 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
687 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
688 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
691 "#else // !MODE_REFRACTION\n"
692 "#ifdef MODE_WATER\n"
693 "varying vec2 TexCoord;\n"
694 "varying vec3 EyeVector;\n"
695 "varying vec4 ModelViewProjectionPosition;\n"
696 "#ifdef VERTEX_SHADER\n"
697 "uniform vec3 EyePosition;\n"
698 "uniform mat4 TexMatrix;\n"
702 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
703 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
704 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
705 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
706 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
707 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
708 " ModelViewProjectionPosition = gl_Position;\n"
712 "#ifdef FRAGMENT_SHADER\n"
713 "uniform sampler2D Texture_Normal;\n"
714 "uniform sampler2D Texture_Refraction;\n"
715 "uniform sampler2D Texture_Reflection;\n"
717 "uniform vec4 DistortScaleRefractReflect;\n"
718 "uniform vec4 ScreenScaleRefractReflect;\n"
719 "uniform vec4 ScreenCenterRefractReflect;\n"
720 "uniform vec4 RefractColor;\n"
721 "uniform vec4 ReflectColor;\n"
722 "uniform float ReflectFactor;\n"
723 "uniform float ReflectOffset;\n"
727 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
728 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
729 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
730 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
731 " // FIXME temporary hack to detect the case that the reflection\n"
732 " // gets blackened at edges due to leaving the area that contains actual\n"
734 " // Remove this 'ack once we have a better way to stop this thing from\n"
736 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
737 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
738 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
739 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
740 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
741 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
742 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
743 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
744 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
745 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
746 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
747 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
750 "#else // !MODE_WATER\n"
752 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
753 "# extension GL_ARB_texture_rectangle : enable\n"
756 "#ifdef USESHADOWMAP2D\n"
757 "# ifdef GL_EXT_gpu_shader4\n"
758 "# extension GL_EXT_gpu_shader4 : enable\n"
760 "# ifdef GL_ARB_texture_gather\n"
761 "# extension GL_ARB_texture_gather : enable\n"
763 "# ifdef GL_AMD_texture_texture4\n"
764 "# extension GL_AMD_texture_texture4 : enable\n"
769 "#ifdef USESHADOWMAPCUBE\n"
770 "# extension GL_EXT_gpu_shader4 : enable\n"
773 "#ifdef USESHADOWSAMPLER\n"
774 "# extension GL_ARB_shadow : enable\n"
777 "// common definitions between vertex shader and fragment shader:\n"
779 "//#ifdef __GLSL_CG_DATA_TYPES\n"
780 "//# define myhalf half\n"
781 "//# define myhalf2 half2\n"
782 "//# define myhalf3half3\n"
783 "//# define myhalf4 half4\n"
785 "# define myhalf float\n"
786 "# define myhalf2 vec2\n"
787 "# define myhalf3 vec3\n"
788 "# define myhalf4 vec4\n"
791 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
795 "varying vec2 TexCoord;\n"
796 "#ifdef USEVERTEXTEXTUREBLEND\n"
797 "varying vec2 TexCoord2;\n"
799 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
800 "#define USELIGHTMAP\n"
801 "varying vec2 TexCoordLightmap;\n"
804 "#ifdef MODE_LIGHTSOURCE\n"
805 "varying vec3 CubeVector;\n"
808 "#ifdef MODE_LIGHTSOURCE\n"
809 "varying vec3 LightVector;\n"
811 "#if defined(MODE_LIGHTDIRECTION)\n"
812 "varying vec3 LightVector;\n"
815 "#if defined(USEOFFSETMAPPING) || defined(USESPECULAR)\n"
816 "//#if defined(USEOFFSETMAPPING) || defined(USESPECULAR) || defined(MODE_LIGHTDIRECTION) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
817 "#define USEEYEVECTOR\n"
818 "varying vec3 EyeVector;\n"
821 "varying vec3 EyeVectorModelSpace;\n"
822 "varying float FogPlaneVertexDist;\n"
825 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
826 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
827 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
828 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
831 "#ifdef USEREFLECTION\n"
832 "varying vec4 ModelViewProjectionPosition;\n"
834 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
835 "uniform vec3 LightPosition;\n"
836 "varying vec4 ModelViewPosition;\n"
839 "#ifdef MODE_LIGHTSOURCE\n"
840 "uniform vec3 LightPosition;\n"
842 "uniform vec3 EyePosition;\n"
843 "#ifdef MODE_LIGHTDIRECTION\n"
844 "uniform vec3 LightDir;\n"
846 "uniform vec4 FogPlane;\n"
852 "// vertex shader specific:\n"
853 "#ifdef VERTEX_SHADER\n"
855 "// 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"
857 "#ifdef MODE_DEFERREDGEOMETRY\n"
858 "uniform mat4 TexMatrix;\n"
859 "#ifdef USEVERTEXTEXTUREBLEND\n"
860 "uniform mat4 BackgroundTexMatrix;\n"
862 "uniform mat4 ModelViewMatrix;\n"
865 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
866 "#ifdef USEVERTEXTEXTUREBLEND\n"
867 " gl_FrontColor = gl_Color;\n"
868 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
871 " // transform unnormalized eye direction into tangent space\n"
872 "#ifdef USEOFFSETMAPPING\n"
873 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
874 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
875 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
876 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
879 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
880 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
881 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
882 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
884 "#else // !MODE_DEFERREDGEOMETRY\n"
885 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
886 "uniform mat4 ModelViewMatrix;\n"
889 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
890 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
892 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
893 "uniform mat4 TexMatrix;\n"
894 "#ifdef USEVERTEXTEXTUREBLEND\n"
895 "uniform mat4 BackgroundTexMatrix;\n"
897 "#ifdef MODE_LIGHTSOURCE\n"
898 "uniform mat4 ModelToLight;\n"
902 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
903 " gl_FrontColor = gl_Color;\n"
905 " // copy the surface texcoord\n"
906 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
907 "#ifdef USEVERTEXTEXTUREBLEND\n"
908 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
910 "#ifdef USELIGHTMAP\n"
911 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
914 "#ifdef MODE_LIGHTSOURCE\n"
915 " // transform vertex position into light attenuation/cubemap space\n"
916 " // (-1 to +1 across the light box)\n"
917 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
919 "# ifdef USEDIFFUSE\n"
920 " // transform unnormalized light direction into tangent space\n"
921 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
922 " // normalize it per pixel)\n"
923 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
924 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
925 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
926 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
930 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
931 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
932 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
933 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
936 " // transform unnormalized eye direction into tangent space\n"
937 "#ifdef USEEYEVECTOR\n"
939 " vec3 EyeVectorModelSpace;\n"
941 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
942 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
943 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
944 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
948 "#ifndef USEEYEVECTOR\n"
949 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
951 " FogPlaneVertexDist = dot(FogPlane, gl_Vertex);\n"
954 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
955 " VectorS = gl_MultiTexCoord1.xyz;\n"
956 " VectorT = gl_MultiTexCoord2.xyz;\n"
957 " VectorR = gl_MultiTexCoord3.xyz;\n"
960 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
961 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
963 "#ifdef USEREFLECTION\n"
964 " ModelViewProjectionPosition = gl_Position;\n"
967 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
968 "#endif // !MODE_DEFERREDGEOMETRY\n"
970 "#endif // VERTEX_SHADER\n"
975 "// fragment shader specific:\n"
976 "#ifdef FRAGMENT_SHADER\n"
978 "uniform sampler2D Texture_Normal;\n"
979 "uniform sampler2D Texture_Color;\n"
980 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
981 "uniform sampler2D Texture_Gloss;\n"
984 "uniform sampler2D Texture_Glow;\n"
986 "#ifdef USEVERTEXTEXTUREBLEND\n"
987 "uniform sampler2D Texture_SecondaryNormal;\n"
988 "uniform sampler2D Texture_SecondaryColor;\n"
989 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
990 "uniform sampler2D Texture_SecondaryGloss;\n"
993 "uniform sampler2D Texture_SecondaryGlow;\n"
996 "#ifdef USECOLORMAPPING\n"
997 "uniform sampler2D Texture_Pants;\n"
998 "uniform sampler2D Texture_Shirt;\n"
1001 "uniform sampler2D Texture_FogMask;\n"
1003 "#ifdef USELIGHTMAP\n"
1004 "uniform sampler2D Texture_Lightmap;\n"
1006 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1007 "uniform sampler2D Texture_Deluxemap;\n"
1009 "#ifdef USEREFLECTION\n"
1010 "uniform sampler2D Texture_Reflection;\n"
1013 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1014 "uniform sampler2DRect Texture_ScreenDepth;\n"
1015 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
1017 "#ifdef USEDEFERREDLIGHTMAP\n"
1018 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
1019 "uniform sampler2DRect Texture_ScreenSpecular;\n"
1022 "uniform myhalf3 Color_Pants;\n"
1023 "uniform myhalf3 Color_Shirt;\n"
1024 "uniform myhalf3 FogColor;\n"
1027 "uniform float FogRangeRecip;\n"
1028 "uniform float FogPlaneViewDist;\n"
1029 "uniform float FogHeightFade;\n"
1030 "myhalf FogVertex(void)\n"
1033 "#ifdef USEFOGOUTSIDE\n"
1034 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1036 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1038 " return myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1042 "#ifdef USEOFFSETMAPPING\n"
1043 "uniform float OffsetMapping_Scale;\n"
1044 "vec2 OffsetMapping(vec2 TexCoord)\n"
1046 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1047 " // 14 sample relief mapping: linear search and then binary search\n"
1048 " // this basically steps forward a small amount repeatedly until it finds\n"
1049 " // itself inside solid, then jitters forward and back using decreasing\n"
1050 " // amounts to find the impact\n"
1051 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1052 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1053 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1054 " vec3 RT = vec3(TexCoord, 1);\n"
1055 " OffsetVector *= 0.1;\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);\n"
1065 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1066 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1067 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1068 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1069 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1072 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1073 " // this basically moves forward the full distance, and then backs up based\n"
1074 " // on height of samples\n"
1075 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1076 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1077 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1078 " TexCoord += OffsetVector;\n"
1079 " OffsetVector *= 0.333;\n"
1080 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1081 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1082 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1083 " return TexCoord;\n"
1086 "#endif // USEOFFSETMAPPING\n"
1088 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1089 "uniform sampler2D Texture_Attenuation;\n"
1090 "uniform samplerCube Texture_Cube;\n"
1092 "#ifdef USESHADOWMAPRECT\n"
1093 "# ifdef USESHADOWSAMPLER\n"
1094 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1096 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1100 "#ifdef USESHADOWMAP2D\n"
1101 "# ifdef USESHADOWSAMPLER\n"
1102 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1104 "uniform sampler2D Texture_ShadowMap2D;\n"
1108 "#ifdef USESHADOWMAPVSDCT\n"
1109 "uniform samplerCube Texture_CubeProjection;\n"
1112 "#ifdef USESHADOWMAPCUBE\n"
1113 "# ifdef USESHADOWSAMPLER\n"
1114 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1116 "uniform samplerCube Texture_ShadowMapCube;\n"
1120 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1121 "uniform vec2 ShadowMap_TextureScale;\n"
1122 "uniform vec4 ShadowMap_Parameters;\n"
1125 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1126 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1128 " vec3 adir = abs(dir);\n"
1129 "# ifndef USESHADOWMAPVSDCT\n"
1133 " if (adir.x > adir.y)\n"
1135 " if (adir.x > adir.z) // X\n"
1139 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1145 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1150 " if (adir.y > adir.z) // Y\n"
1154 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1160 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1164 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1165 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1166 " stc.z += ShadowMap_Parameters.z;\n"
1169 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1170 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1171 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1172 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1173 " stc.z += ShadowMap_Parameters.z;\n"
1177 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1179 "#ifdef USESHADOWMAPCUBE\n"
1180 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1182 " vec3 adir = abs(dir);\n"
1183 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1187 "# ifdef USESHADOWMAPRECT\n"
1188 "float ShadowMapCompare(vec3 dir)\n"
1190 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1192 "# ifdef USESHADOWSAMPLER\n"
1194 "# ifdef USESHADOWMAPPCF\n"
1195 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1196 " 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"
1198 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1203 "# ifdef USESHADOWMAPPCF\n"
1204 "# if USESHADOWMAPPCF > 1\n"
1205 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1206 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1207 " 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"
1208 " 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"
1209 " 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"
1210 " 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"
1211 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1212 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1214 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1215 " vec2 offset = fract(shadowmaptc.xy);\n"
1216 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1217 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1218 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1219 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1220 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1223 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1231 "# ifdef USESHADOWMAP2D\n"
1232 "float ShadowMapCompare(vec3 dir)\n"
1234 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1237 "# ifdef USESHADOWSAMPLER\n"
1238 "# ifdef USESHADOWMAPPCF\n"
1239 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1240 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1241 " 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"
1243 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1246 "# ifdef USESHADOWMAPPCF\n"
1247 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1248 "# ifdef GL_ARB_texture_gather\n"
1249 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1251 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1253 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1254 " center *= ShadowMap_TextureScale;\n"
1255 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1256 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1257 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1258 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1259 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1260 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1261 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1263 "# ifdef GL_EXT_gpu_shader4\n"
1264 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1266 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1268 "# if USESHADOWMAPPCF > 1\n"
1269 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1270 " center *= ShadowMap_TextureScale;\n"
1271 " 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"
1272 " 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"
1273 " 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"
1274 " 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"
1275 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1276 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1278 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1279 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1280 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1281 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1282 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1283 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1287 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1294 "# ifdef USESHADOWMAPCUBE\n"
1295 "float ShadowMapCompare(vec3 dir)\n"
1297 " // apply depth texture cubemap as light filter\n"
1298 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1300 "# ifdef USESHADOWSAMPLER\n"
1301 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1303 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1308 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1310 "#ifdef MODE_DEFERREDGEOMETRY\n"
1313 "#ifdef USEOFFSETMAPPING\n"
1314 " // apply offsetmapping\n"
1315 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1316 "#define TexCoord TexCoordOffset\n"
1319 "#ifdef USEALPHAKILL\n"
1320 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1324 "#ifdef USEVERTEXTEXTUREBLEND\n"
1325 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1326 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1327 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1328 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1331 "#ifdef USEVERTEXTEXTUREBLEND\n"
1332 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1334 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1337 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1339 "#else // !MODE_DEFERREDGEOMETRY\n"
1340 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1341 "uniform mat4 ViewToLight;\n"
1342 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1343 "uniform vec2 ScreenToDepth;\n"
1344 "uniform myhalf3 DeferredColor_Ambient;\n"
1345 "uniform myhalf3 DeferredColor_Diffuse;\n"
1346 "#ifdef USESPECULAR\n"
1347 "uniform myhalf3 DeferredColor_Specular;\n"
1348 "uniform myhalf SpecularPower;\n"
1352 " // calculate viewspace pixel position\n"
1354 " position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1355 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1356 " // decode viewspace pixel normal\n"
1357 " myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1358 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1359 " // surfacenormal = pixel normal in viewspace\n"
1360 " // LightVector = pixel to light in viewspace\n"
1361 " // CubeVector = position in lightspace\n"
1362 " // eyevector = pixel to view in viewspace\n"
1363 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1364 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1365 "#ifdef USEDIFFUSE\n"
1366 " // calculate diffuse shading\n"
1367 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1368 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1370 "#ifdef USESPECULAR\n"
1371 " // calculate directional shading\n"
1372 " vec3 eyevector = position * -1.0;\n"
1373 "# ifdef USEEXACTSPECULARMATH\n"
1374 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1376 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1377 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1381 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1382 " fade *= ShadowMapCompare(CubeVector);\n"
1385 "#ifdef USEDIFFUSE\n"
1386 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1388 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1390 "#ifdef USESPECULAR\n"
1391 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1393 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1396 "# ifdef USECUBEFILTER\n"
1397 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1398 " gl_FragData[0] *= cubecolor;\n"
1399 " gl_FragData[1] *= cubecolor;\n"
1402 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1403 "#ifdef USEDEFERREDLIGHTMAP\n"
1404 "uniform myhalf3 DeferredMod_Diffuse;\n"
1405 "uniform myhalf3 DeferredMod_Specular;\n"
1407 "uniform myhalf3 Color_Ambient;\n"
1408 "uniform myhalf3 Color_Diffuse;\n"
1409 "uniform myhalf3 Color_Specular;\n"
1410 "uniform myhalf SpecularPower;\n"
1412 "uniform myhalf3 Color_Glow;\n"
1414 "uniform myhalf Alpha;\n"
1415 "#ifdef USEREFLECTION\n"
1416 "uniform vec4 DistortScaleRefractReflect;\n"
1417 "uniform vec4 ScreenScaleRefractReflect;\n"
1418 "uniform vec4 ScreenCenterRefractReflect;\n"
1419 "uniform myhalf4 ReflectColor;\n"
1421 "#ifdef MODE_LIGHTDIRECTION\n"
1422 "uniform myhalf3 LightColor;\n"
1424 "#ifdef MODE_LIGHTSOURCE\n"
1425 "uniform myhalf3 LightColor;\n"
1429 "#ifdef USEOFFSETMAPPING\n"
1430 " // apply offsetmapping\n"
1431 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1432 "#define TexCoord TexCoordOffset\n"
1435 " // combine the diffuse textures (base, pants, shirt)\n"
1436 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1437 "#ifdef USEALPHAKILL\n"
1438 " if (color.a < 0.5)\n"
1441 " color.a *= Alpha;\n"
1442 "#ifdef USECOLORMAPPING\n"
1443 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1445 "#ifdef USEVERTEXTEXTUREBLEND\n"
1446 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1447 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1448 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1449 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1451 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1454 " // get the surface normal\n"
1455 "#ifdef USEVERTEXTEXTUREBLEND\n"
1456 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1458 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1461 " // get the material colors\n"
1462 " myhalf3 diffusetex = color.rgb;\n"
1463 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1464 "# ifdef USEVERTEXTEXTUREBLEND\n"
1465 " myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1467 " myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1474 "#ifdef MODE_LIGHTSOURCE\n"
1475 " // light source\n"
1476 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1477 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1478 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1479 "#ifdef USESPECULAR\n"
1480 "#ifdef USEEXACTSPECULARMATH\n"
1481 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1483 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1484 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1486 " color.rgb += glosstex * (specular * Color_Specular);\n"
1488 " color.rgb *= LightColor;\n"
1489 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1490 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1491 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1493 "# ifdef USECUBEFILTER\n"
1494 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1496 "#endif // MODE_LIGHTSOURCE\n"
1501 "#ifdef MODE_LIGHTDIRECTION\n"
1503 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1504 "#define lightcolor LightColor\n"
1505 "#endif // MODE_LIGHTDIRECTION\n"
1506 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1508 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1509 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1510 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1511 " // convert modelspace light vector to tangentspace\n"
1512 " myhalf3 lightnormal;\n"
1513 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1514 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1515 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1516 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1517 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1518 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1519 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1520 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1521 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1522 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1523 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1524 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1525 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1526 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1527 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1529 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1530 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1531 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1537 "#ifdef MODE_LIGHTMAP\n"
1538 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1539 "#endif // MODE_LIGHTMAP\n"
1540 "#ifdef MODE_VERTEXCOLOR\n"
1541 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1542 "#endif // MODE_VERTEXCOLOR\n"
1543 "#ifdef MODE_FLATCOLOR\n"
1544 " color.rgb = diffusetex * Color_Ambient;\n"
1545 "#endif // MODE_FLATCOLOR\n"
1551 "# ifdef USEDIFFUSE\n"
1552 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1553 "# ifdef USESPECULAR\n"
1554 "# ifdef USEEXACTSPECULARMATH\n"
1555 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1557 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1558 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1560 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1562 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1565 " color.rgb = diffusetex * Color_Ambient;\n"
1569 "#ifdef USEDEFERREDLIGHTMAP\n"
1570 " color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1571 " color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1575 "#ifdef USEVERTEXTEXTUREBLEND\n"
1576 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1578 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1583 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1586 " // 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"
1587 "#ifdef USEREFLECTION\n"
1588 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1589 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1590 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1591 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1592 " // FIXME temporary hack to detect the case that the reflection\n"
1593 " // gets blackened at edges due to leaving the area that contains actual\n"
1595 " // Remove this 'ack once we have a better way to stop this thing from\n"
1597 " float 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 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1601 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1602 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1605 " gl_FragColor = vec4(color);\n"
1607 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1608 "#endif // !MODE_DEFERREDGEOMETRY\n"
1610 "#endif // FRAGMENT_SHADER\n"
1612 "#endif // !MODE_WATER\n"
1613 "#endif // !MODE_REFRACTION\n"
1614 "#endif // !MODE_BLOOMBLUR\n"
1615 "#endif // !MODE_GENERIC\n"
1616 "#endif // !MODE_POSTPROCESS\n"
1617 "#endif // !MODE_SHOWDEPTH\n"
1618 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1621 const char *builtincgshaderstring = "";
1623 typedef struct shaderpermutationinfo_s
1625 const char *pretext;
1628 shaderpermutationinfo_t;
1630 typedef struct shadermodeinfo_s
1632 const char *vertexfilename;
1633 const char *geometryfilename;
1634 const char *fragmentfilename;
1635 const char *pretext;
1640 typedef enum shaderpermutation_e
1642 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1643 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1644 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
1645 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
1646 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
1647 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
1648 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
1649 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
1650 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
1651 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
1652 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
1653 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
1654 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
1655 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1656 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1657 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
1658 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1659 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
1660 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
1661 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
1662 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
1663 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1664 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
1665 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1666 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
1667 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
1668 SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
1669 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
1671 shaderpermutation_t;
1673 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1674 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1676 {"#define USEDIFFUSE\n", " diffuse"},
1677 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1678 {"#define USEVIEWTINT\n", " viewtint"},
1679 {"#define USECOLORMAPPING\n", " colormapping"},
1680 {"#define USESATURATION\n", " saturation"},
1681 {"#define USEFOGINSIDE\n", " foginside"},
1682 {"#define USEFOGOUTSIDE\n", " fogoutside"},
1683 {"#define USEGAMMARAMPS\n", " gammaramps"},
1684 {"#define USECUBEFILTER\n", " cubefilter"},
1685 {"#define USEGLOW\n", " glow"},
1686 {"#define USEBLOOM\n", " bloom"},
1687 {"#define USESPECULAR\n", " specular"},
1688 {"#define USEPOSTPROCESSING\n", " postprocessing"},
1689 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1690 {"#define USEREFLECTION\n", " reflection"},
1691 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1692 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1693 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1694 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1695 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1696 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1697 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1698 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1699 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1700 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
1701 {"#define USEALPHAKILL\n", " alphakill"},
1704 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1705 typedef enum shadermode_e
1707 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1708 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1709 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1710 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1711 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1712 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1713 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1714 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1715 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1716 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1717 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1718 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1719 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1720 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
1721 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
1726 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1727 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
1729 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1730 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1731 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1732 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1733 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1734 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1735 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1736 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1737 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1738 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1739 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1740 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1741 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1742 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1743 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1747 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
1749 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
1750 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
1751 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1752 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
1753 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1754 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
1755 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1756 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1757 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1758 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1759 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
1760 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
1761 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
1762 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
1763 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
1767 struct r_glsl_permutation_s;
1768 typedef struct r_glsl_permutation_s
1770 /// hash lookup data
1771 struct r_glsl_permutation_s *hashnext;
1773 unsigned int permutation;
1775 /// indicates if we have tried compiling this permutation already
1777 /// 0 if compilation failed
1779 /// locations of detected uniforms in program object, or -1 if not found
1780 int loc_Texture_First;
1781 int loc_Texture_Second;
1782 int loc_Texture_GammaRamps;
1783 int loc_Texture_Normal;
1784 int loc_Texture_Color;
1785 int loc_Texture_Gloss;
1786 int loc_Texture_Glow;
1787 int loc_Texture_SecondaryNormal;
1788 int loc_Texture_SecondaryColor;
1789 int loc_Texture_SecondaryGloss;
1790 int loc_Texture_SecondaryGlow;
1791 int loc_Texture_Pants;
1792 int loc_Texture_Shirt;
1793 int loc_Texture_FogMask;
1794 int loc_Texture_Lightmap;
1795 int loc_Texture_Deluxemap;
1796 int loc_Texture_Attenuation;
1797 int loc_Texture_Cube;
1798 int loc_Texture_Refraction;
1799 int loc_Texture_Reflection;
1800 int loc_Texture_ShadowMapRect;
1801 int loc_Texture_ShadowMapCube;
1802 int loc_Texture_ShadowMap2D;
1803 int loc_Texture_CubeProjection;
1804 int loc_Texture_ScreenDepth;
1805 int loc_Texture_ScreenNormalMap;
1806 int loc_Texture_ScreenDiffuse;
1807 int loc_Texture_ScreenSpecular;
1809 int loc_BloomBlur_Parameters;
1811 int loc_Color_Ambient;
1812 int loc_Color_Diffuse;
1813 int loc_Color_Specular;
1815 int loc_Color_Pants;
1816 int loc_Color_Shirt;
1817 int loc_DeferredColor_Ambient;
1818 int loc_DeferredColor_Diffuse;
1819 int loc_DeferredColor_Specular;
1820 int loc_DeferredMod_Diffuse;
1821 int loc_DeferredMod_Specular;
1822 int loc_DistortScaleRefractReflect;
1823 int loc_EyePosition;
1825 int loc_FogHeightFade;
1827 int loc_FogPlaneViewDist;
1828 int loc_FogRangeRecip;
1831 int loc_LightPosition;
1832 int loc_OffsetMapping_Scale;
1834 int loc_ReflectColor;
1835 int loc_ReflectFactor;
1836 int loc_ReflectOffset;
1837 int loc_RefractColor;
1839 int loc_ScreenCenterRefractReflect;
1840 int loc_ScreenScaleRefractReflect;
1841 int loc_ScreenToDepth;
1842 int loc_ShadowMap_Parameters;
1843 int loc_ShadowMap_TextureScale;
1844 int loc_SpecularPower;
1849 int loc_ViewTintColor;
1850 int loc_ViewToLight;
1851 int loc_ModelToLight;
1853 int loc_BackgroundTexMatrix;
1854 int loc_ModelViewProjectionMatrix;
1855 int loc_ModelViewMatrix;
1857 r_glsl_permutation_t;
1859 #define SHADERPERMUTATION_HASHSIZE 256
1861 /// information about each possible shader permutation
1862 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1863 /// currently selected permutation
1864 r_glsl_permutation_t *r_glsl_permutation;
1865 /// storage for permutations linked in the hash table
1866 memexpandablearray_t r_glsl_permutationarray;
1868 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1870 //unsigned int hashdepth = 0;
1871 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1872 r_glsl_permutation_t *p;
1873 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1875 if (p->mode == mode && p->permutation == permutation)
1877 //if (hashdepth > 10)
1878 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1883 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1885 p->permutation = permutation;
1886 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1887 r_glsl_permutationhash[mode][hashindex] = p;
1888 //if (hashdepth > 10)
1889 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1893 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1896 if (!filename || !filename[0])
1898 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1901 if (printfromdisknotice)
1902 Con_DPrintf("from disk %s... ", filename);
1903 return shaderstring;
1905 else if (!strcmp(filename, "glsl/default.glsl"))
1907 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1908 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1910 return shaderstring;
1913 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1916 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1917 int vertstrings_count = 0;
1918 int geomstrings_count = 0;
1919 int fragstrings_count = 0;
1920 char *vertexstring, *geometrystring, *fragmentstring;
1921 const char *vertstrings_list[32+3];
1922 const char *geomstrings_list[32+3];
1923 const char *fragstrings_list[32+3];
1924 char permutationname[256];
1931 permutationname[0] = 0;
1932 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1933 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1934 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1936 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1938 // the first pretext is which type of shader to compile as
1939 // (later these will all be bound together as a program object)
1940 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1941 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1942 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1944 // the second pretext is the mode (for example a light source)
1945 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1946 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1947 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1948 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1950 // now add all the permutation pretexts
1951 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1953 if (permutation & (1<<i))
1955 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1956 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1957 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1958 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1962 // keep line numbers correct
1963 vertstrings_list[vertstrings_count++] = "\n";
1964 geomstrings_list[geomstrings_count++] = "\n";
1965 fragstrings_list[fragstrings_count++] = "\n";
1969 // now append the shader text itself
1970 vertstrings_list[vertstrings_count++] = vertexstring;
1971 geomstrings_list[geomstrings_count++] = geometrystring;
1972 fragstrings_list[fragstrings_count++] = fragmentstring;
1974 // if any sources were NULL, clear the respective list
1976 vertstrings_count = 0;
1977 if (!geometrystring)
1978 geomstrings_count = 0;
1979 if (!fragmentstring)
1980 fragstrings_count = 0;
1982 // compile the shader program
1983 if (vertstrings_count + geomstrings_count + fragstrings_count)
1984 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1988 qglUseProgramObjectARB(p->program);CHECKGLERROR
1989 // look up all the uniform variable names we care about, so we don't
1990 // have to look them up every time we set them
1992 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1993 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1994 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1995 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1996 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1997 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1998 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1999 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
2000 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
2001 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
2002 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
2003 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
2004 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
2005 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
2006 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
2007 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
2008 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
2009 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
2010 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
2011 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
2012 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
2013 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
2014 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
2015 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
2016 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
2017 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
2018 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
2019 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
2020 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
2021 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
2022 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
2023 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
2024 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
2025 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
2026 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
2027 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
2028 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
2029 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
2030 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
2031 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
2032 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
2033 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
2034 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
2035 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
2036 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
2037 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
2038 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
2039 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
2040 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
2041 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
2042 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
2043 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
2044 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
2045 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
2046 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
2047 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
2048 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
2049 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
2050 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
2051 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
2052 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
2053 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
2054 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
2055 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
2056 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
2057 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
2058 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
2059 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
2060 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
2061 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
2062 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
2063 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
2064 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
2065 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
2066 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
2067 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
2068 // initialize the samplers to refer to the texture units we use
2069 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
2070 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
2071 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
2072 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
2073 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
2074 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
2075 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
2076 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
2077 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
2078 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
2079 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
2080 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
2081 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
2082 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
2083 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
2084 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
2085 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
2086 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
2087 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
2088 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
2089 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
2090 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
2091 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
2092 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
2093 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
2094 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
2095 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
2096 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
2098 if (developer.integer)
2099 Con_Printf("^5GLSL shader %s compiled.\n", permutationname);
2102 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
2106 Mem_Free(vertexstring);
2108 Mem_Free(geometrystring);
2110 Mem_Free(fragmentstring);
2113 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
2115 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
2116 if (r_glsl_permutation != perm)
2118 r_glsl_permutation = perm;
2119 if (!r_glsl_permutation->program)
2121 if (!r_glsl_permutation->compiled)
2122 R_GLSL_CompilePermutation(perm, mode, permutation);
2123 if (!r_glsl_permutation->program)
2125 // remove features until we find a valid permutation
2127 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2129 // reduce i more quickly whenever it would not remove any bits
2130 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2131 if (!(permutation & j))
2134 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2135 if (!r_glsl_permutation->compiled)
2136 R_GLSL_CompilePermutation(perm, mode, permutation);
2137 if (r_glsl_permutation->program)
2140 if (i >= SHADERPERMUTATION_COUNT)
2142 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2143 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
2144 qglUseProgramObjectARB(0);CHECKGLERROR
2145 return; // no bit left to clear, entire mode is broken
2150 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
2152 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
2156 #include <Cg/cgGL.h>
2157 struct r_cg_permutation_s;
2158 typedef struct r_cg_permutation_s
2160 /// hash lookup data
2161 struct r_cg_permutation_s *hashnext;
2163 unsigned int permutation;
2165 /// indicates if we have tried compiling this permutation already
2167 /// 0 if compilation failed
2170 /// locations of detected parameters in programs, or NULL if not found
2171 CGparameter vp_EyePosition;
2172 CGparameter vp_FogPlane;
2173 CGparameter vp_LightDir;
2174 CGparameter vp_LightPosition;
2175 CGparameter vp_ModelToLight;
2176 CGparameter vp_TexMatrix;
2177 CGparameter vp_BackgroundTexMatrix;
2178 CGparameter vp_ModelViewProjectionMatrix;
2179 CGparameter vp_ModelViewMatrix;
2181 CGparameter fp_Texture_First;
2182 CGparameter fp_Texture_Second;
2183 CGparameter fp_Texture_GammaRamps;
2184 CGparameter fp_Texture_Normal;
2185 CGparameter fp_Texture_Color;
2186 CGparameter fp_Texture_Gloss;
2187 CGparameter fp_Texture_Glow;
2188 CGparameter fp_Texture_SecondaryNormal;
2189 CGparameter fp_Texture_SecondaryColor;
2190 CGparameter fp_Texture_SecondaryGloss;
2191 CGparameter fp_Texture_SecondaryGlow;
2192 CGparameter fp_Texture_Pants;
2193 CGparameter fp_Texture_Shirt;
2194 CGparameter fp_Texture_FogMask;
2195 CGparameter fp_Texture_Lightmap;
2196 CGparameter fp_Texture_Deluxemap;
2197 CGparameter fp_Texture_Attenuation;
2198 CGparameter fp_Texture_Cube;
2199 CGparameter fp_Texture_Refraction;
2200 CGparameter fp_Texture_Reflection;
2201 CGparameter fp_Texture_ShadowMapRect;
2202 CGparameter fp_Texture_ShadowMapCube;
2203 CGparameter fp_Texture_ShadowMap2D;
2204 CGparameter fp_Texture_CubeProjection;
2205 CGparameter fp_Texture_ScreenDepth;
2206 CGparameter fp_Texture_ScreenNormalMap;
2207 CGparameter fp_Texture_ScreenDiffuse;
2208 CGparameter fp_Texture_ScreenSpecular;
2209 CGparameter fp_Alpha;
2210 CGparameter fp_BloomBlur_Parameters;
2211 CGparameter fp_ClientTime;
2212 CGparameter fp_Color_Ambient;
2213 CGparameter fp_Color_Diffuse;
2214 CGparameter fp_Color_Specular;
2215 CGparameter fp_Color_Glow;
2216 CGparameter fp_Color_Pants;
2217 CGparameter fp_Color_Shirt;
2218 CGparameter fp_DeferredColor_Ambient;
2219 CGparameter fp_DeferredColor_Diffuse;
2220 CGparameter fp_DeferredColor_Specular;
2221 CGparameter fp_DeferredMod_Diffuse;
2222 CGparameter fp_DeferredMod_Specular;
2223 CGparameter fp_DistortScaleRefractReflect;
2224 CGparameter fp_EyePosition;
2225 CGparameter fp_FogColor;
2226 CGparameter fp_FogHeightFade;
2227 CGparameter fp_FogPlane;
2228 CGparameter fp_FogPlaneViewDist;
2229 CGparameter fp_FogRangeRecip;
2230 CGparameter fp_LightColor;
2231 CGparameter fp_LightDir;
2232 CGparameter fp_LightPosition;
2233 CGparameter fp_OffsetMapping_Scale;
2234 CGparameter fp_PixelSize;
2235 CGparameter fp_ReflectColor;
2236 CGparameter fp_ReflectFactor;
2237 CGparameter fp_ReflectOffset;
2238 CGparameter fp_RefractColor;
2239 CGparameter fp_Saturation;
2240 CGparameter fp_ScreenCenterRefractReflect;
2241 CGparameter fp_ScreenScaleRefractReflect;
2242 CGparameter fp_ScreenToDepth;
2243 CGparameter fp_ShadowMap_Parameters;
2244 CGparameter fp_ShadowMap_TextureScale;
2245 CGparameter fp_SpecularPower;
2246 CGparameter fp_UserVec1;
2247 CGparameter fp_UserVec2;
2248 CGparameter fp_UserVec3;
2249 CGparameter fp_UserVec4;
2250 CGparameter fp_ViewTintColor;
2251 CGparameter fp_ViewToLight;
2255 /// information about each possible shader permutation
2256 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
2257 /// currently selected permutation
2258 r_cg_permutation_t *r_cg_permutation;
2259 /// storage for permutations linked in the hash table
2260 memexpandablearray_t r_cg_permutationarray;
2262 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
2264 //unsigned int hashdepth = 0;
2265 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
2266 r_cg_permutation_t *p;
2267 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
2269 if (p->mode == mode && p->permutation == permutation)
2271 //if (hashdepth > 10)
2272 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
2277 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
2279 p->permutation = permutation;
2280 p->hashnext = r_cg_permutationhash[mode][hashindex];
2281 r_cg_permutationhash[mode][hashindex] = p;
2282 //if (hashdepth > 10)
2283 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
2287 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
2290 if (!filename || !filename[0])
2292 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
2295 if (printfromdisknotice)
2296 Con_DPrintf("from disk %s... ", filename);
2297 return shaderstring;
2299 else if (!strcmp(filename, "cg/default.cg"))
2301 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
2302 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
2304 return shaderstring;
2307 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
2310 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
2311 int vertstrings_count = 0, vertstring_length = 0;
2312 int geomstrings_count = 0, geomstring_length = 0;
2313 int fragstrings_count = 0, fragstring_length = 0;
2315 char *vertexstring, *geometrystring, *fragmentstring;
2316 char *vertstring, *geomstring, *fragstring;
2317 const char *vertstrings_list[32+3];
2318 const char *geomstrings_list[32+3];
2319 const char *fragstrings_list[32+3];
2320 char permutationname[256];
2328 permutationname[0] = 0;
2329 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
2330 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
2331 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
2333 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
2335 // the first pretext is which type of shader to compile as
2336 // (later these will all be bound together as a program object)
2337 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
2338 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
2339 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
2341 // the second pretext is the mode (for example a light source)
2342 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
2343 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
2344 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
2345 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
2347 // now add all the permutation pretexts
2348 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2350 if (permutation & (1<<i))
2352 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
2353 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
2354 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
2355 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
2359 // keep line numbers correct
2360 vertstrings_list[vertstrings_count++] = "\n";
2361 geomstrings_list[geomstrings_count++] = "\n";
2362 fragstrings_list[fragstrings_count++] = "\n";
2366 // now append the shader text itself
2367 vertstrings_list[vertstrings_count++] = vertexstring;
2368 geomstrings_list[geomstrings_count++] = geometrystring;
2369 fragstrings_list[fragstrings_count++] = fragmentstring;
2371 // if any sources were NULL, clear the respective list
2373 vertstrings_count = 0;
2374 if (!geometrystring)
2375 geomstrings_count = 0;
2376 if (!fragmentstring)
2377 fragstrings_count = 0;
2379 vertstring_length = 0;
2380 for (i = 0;i < vertstrings_count;i++)
2381 vertstring_length += strlen(vertstrings_list[i]);
2382 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
2383 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
2384 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
2386 geomstring_length = 0;
2387 for (i = 0;i < geomstrings_count;i++)
2388 geomstring_length += strlen(geomstrings_list[i]);
2389 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
2390 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
2391 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
2393 fragstring_length = 0;
2394 for (i = 0;i < fragstrings_count;i++)
2395 fragstring_length += strlen(fragstrings_list[i]);
2396 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
2397 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
2398 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
2400 // compile the shader program
2401 if (vertstring[0] || geomstring[0] || fragstring[0])
2404 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL);
2406 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL);
2411 cgGLBindProgram(p->vprogram);
2412 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2415 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2418 cgGLBindProgram(p->fprogram);
2419 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2422 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2424 if (p->vprogram || p->fprogram)
2426 // look up all the uniform variable names we care about, so we don't
2427 // have to look them up every time we set them
2428 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
2429 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
2430 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
2431 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
2432 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
2433 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
2434 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
2435 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
2436 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
2438 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
2439 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
2440 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
2441 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
2442 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
2443 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
2444 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
2445 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
2446 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
2447 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
2448 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
2449 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
2450 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
2451 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
2452 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
2453 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
2454 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
2455 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
2456 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
2457 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
2458 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
2459 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
2460 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
2461 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
2462 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
2463 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
2464 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
2465 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
2466 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
2467 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
2468 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
2469 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
2470 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
2471 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
2472 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
2473 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
2474 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
2475 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
2476 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
2477 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
2478 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
2479 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
2480 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
2481 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
2482 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
2483 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
2484 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
2485 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
2486 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
2487 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
2488 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
2489 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
2490 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
2491 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
2492 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
2493 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
2494 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
2495 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
2496 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
2497 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
2498 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
2499 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
2500 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
2501 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
2502 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
2503 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
2504 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
2505 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
2506 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
2507 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
2508 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
2510 if (developer.integer)
2511 Con_Printf("^5CG shader %s compiled.\n", permutationname);
2514 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
2518 Mem_Free(vertstring);
2520 Mem_Free(geomstring);
2522 Mem_Free(fragstring);
2524 Mem_Free(vertexstring);
2526 Mem_Free(geometrystring);
2528 Mem_Free(fragmentstring);
2531 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
2533 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
2534 if (r_cg_permutation != perm)
2536 r_cg_permutation = perm;
2537 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));
2538 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2539 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
2541 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2542 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2543 if (!r_cg_permutation->compiled)
2544 R_CG_CompilePermutation(perm, mode, permutation);
2545 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
2547 // remove features until we find a valid permutation
2549 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2551 // reduce i more quickly whenever it would not remove any bits
2552 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
2553 if (!(permutation & j))
2556 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
2557 if (!r_cg_permutation->compiled)
2558 R_CG_CompilePermutation(perm, mode, permutation);
2559 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
2562 if (i >= SHADERPERMUTATION_COUNT)
2564 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
2565 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
2566 return; // no bit left to clear, entire mode is broken
2571 if (r_cg_permutation->vprogram)
2573 cgGLBindProgram(r_cg_permutation->vprogram);
2574 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2577 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));
2578 if (r_cg_permutation->fprogram)
2580 cgGLBindProgram(r_cg_permutation->fprogram);
2581 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2584 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));
2586 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);
2590 void R_GLSL_Restart_f(void)
2592 unsigned int i, limit;
2593 r_glsl_permutation_t *p;
2594 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
2595 for (i = 0;i < limit;i++)
2597 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
2599 GL_Backend_FreeProgram(p->program);
2600 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
2603 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2607 r_cg_permutation_t *p;
2608 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
2609 for (i = 0;i < limit;i++)
2611 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
2614 cgDestroyProgram(p->vprogram);
2616 cgDestroyProgram(p->fprogram);
2617 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
2620 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
2625 void R_GLSL_DumpShader_f(void)
2630 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
2633 FS_Print(file, "/* The engine may define the following macros:\n");
2634 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2635 for (i = 0;i < SHADERMODE_COUNT;i++)
2636 FS_Print(file, glslshadermodeinfo[i].pretext);
2637 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2638 FS_Print(file, shaderpermutationinfo[i].pretext);
2639 FS_Print(file, "*/\n");
2640 FS_Print(file, builtinshaderstring);
2642 Con_Printf("glsl/default.glsl written\n");
2645 Con_Printf("failed to write to glsl/default.glsl\n");
2648 file = FS_OpenRealFile("cg/default.cg", "w", false);
2651 FS_Print(file, "/* The engine may define the following macros:\n");
2652 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2653 for (i = 0;i < SHADERMODE_COUNT;i++)
2654 FS_Print(file, cgshadermodeinfo[i].pretext);
2655 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2656 FS_Print(file, shaderpermutationinfo[i].pretext);
2657 FS_Print(file, "*/\n");
2658 FS_Print(file, builtincgshaderstring);
2660 Con_Printf("cg/default.cg written\n");
2663 Con_Printf("failed to write to cg/default.cg\n");
2667 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
2670 texturemode = GL_MODULATE;
2671 switch (vid.renderpath)
2673 case RENDERPATH_GL20:
2674 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
2675 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(first ));
2676 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, R_GetTexture(second));
2678 case RENDERPATH_CGGL:
2680 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
2681 if (r_cg_permutation->fp_Texture_First ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First , R_GetTexture(first ));
2682 if (r_cg_permutation->fp_Texture_Second) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second, R_GetTexture(second));
2685 case RENDERPATH_GL13:
2686 R_Mesh_TexBind(0, R_GetTexture(first ));
2687 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2688 R_Mesh_TexBind(1, R_GetTexture(second));
2690 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2692 case RENDERPATH_GL11:
2693 R_Mesh_TexBind(0, R_GetTexture(first ));
2698 void R_SetupShader_DepthOrShadow(void)
2700 switch (vid.renderpath)
2702 case RENDERPATH_GL20:
2703 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
2705 case RENDERPATH_CGGL:
2707 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
2710 case RENDERPATH_GL13:
2711 R_Mesh_TexBind(0, 0);
2712 R_Mesh_TexBind(1, 0);
2714 case RENDERPATH_GL11:
2715 R_Mesh_TexBind(0, 0);
2720 void R_SetupShader_ShowDepth(void)
2722 switch (vid.renderpath)
2724 case RENDERPATH_GL20:
2725 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
2727 case RENDERPATH_CGGL:
2729 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
2732 case RENDERPATH_GL13:
2734 case RENDERPATH_GL11:
2739 extern qboolean r_shadow_usingdeferredprepass;
2740 extern cvar_t r_shadow_deferred_8bitrange;
2741 extern rtexture_t *r_shadow_attenuationgradienttexture;
2742 extern rtexture_t *r_shadow_attenuation2dtexture;
2743 extern rtexture_t *r_shadow_attenuation3dtexture;
2744 extern qboolean r_shadow_usingshadowmaprect;
2745 extern qboolean r_shadow_usingshadowmapcube;
2746 extern qboolean r_shadow_usingshadowmap2d;
2747 extern float r_shadow_shadowmap_texturescale[2];
2748 extern float r_shadow_shadowmap_parameters[4];
2749 extern qboolean r_shadow_shadowmapvsdct;
2750 extern qboolean r_shadow_shadowmapsampler;
2751 extern int r_shadow_shadowmappcf;
2752 extern rtexture_t *r_shadow_shadowmaprectangletexture;
2753 extern rtexture_t *r_shadow_shadowmap2dtexture;
2754 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
2755 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2756 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2757 extern int r_shadow_prepass_width;
2758 extern int r_shadow_prepass_height;
2759 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2760 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2761 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2762 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2763 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2765 // select a permutation of the lighting shader appropriate to this
2766 // combination of texture, entity, light source, and fogging, only use the
2767 // minimum features necessary to avoid wasting rendering time in the
2768 // fragment shader on features that are not being used
2769 unsigned int permutation = 0;
2770 unsigned int mode = 0;
2772 // TODO: implement geometry-shader based shadow volumes someday
2773 if (r_glsl_offsetmapping.integer)
2775 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2776 if (r_glsl_offsetmapping_reliefmapping.integer)
2777 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2779 if (rsurfacepass == RSURFPASS_BACKGROUND)
2781 // distorted background
2782 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2783 mode = SHADERMODE_WATER;
2785 mode = SHADERMODE_REFRACTION;
2787 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2789 // normalmap (deferred prepass), may use alpha test on diffuse
2790 mode = SHADERMODE_DEFERREDGEOMETRY;
2791 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2792 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2793 if (r_glsl_offsetmapping.integer)
2795 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2796 if (r_glsl_offsetmapping_reliefmapping.integer)
2797 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2800 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2803 mode = SHADERMODE_LIGHTSOURCE;
2804 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2805 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2806 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2807 permutation |= SHADERPERMUTATION_CUBEFILTER;
2808 if (diffusescale > 0)
2809 permutation |= SHADERPERMUTATION_DIFFUSE;
2810 if (specularscale > 0)
2811 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2812 if (r_refdef.fogenabled)
2813 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2814 if (rsurface.texture->colormapping)
2815 permutation |= SHADERPERMUTATION_COLORMAPPING;
2816 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2818 if (r_shadow_usingshadowmaprect)
2819 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2820 if (r_shadow_usingshadowmap2d)
2821 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2822 if (r_shadow_usingshadowmapcube)
2823 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2824 else if(r_shadow_shadowmapvsdct)
2825 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2827 if (r_shadow_shadowmapsampler)
2828 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2829 if (r_shadow_shadowmappcf > 1)
2830 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2831 else if (r_shadow_shadowmappcf)
2832 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2835 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2837 // unshaded geometry (fullbright or ambient model lighting)
2838 mode = SHADERMODE_FLATCOLOR;
2839 ambientscale = diffusescale = specularscale = 0;
2840 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2841 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2842 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2843 permutation |= SHADERPERMUTATION_GLOW;
2844 if (r_refdef.fogenabled)
2845 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2846 if (rsurface.texture->colormapping)
2847 permutation |= SHADERPERMUTATION_COLORMAPPING;
2848 if (r_glsl_offsetmapping.integer)
2850 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2851 if (r_glsl_offsetmapping_reliefmapping.integer)
2852 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2854 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2855 permutation |= SHADERPERMUTATION_REFLECTION;
2857 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2859 // directional model lighting
2860 mode = SHADERMODE_LIGHTDIRECTION;
2861 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2862 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2863 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2864 permutation |= SHADERPERMUTATION_GLOW;
2865 permutation |= SHADERPERMUTATION_DIFFUSE;
2866 if (specularscale > 0)
2867 permutation |= SHADERPERMUTATION_SPECULAR;
2868 if (r_refdef.fogenabled)
2869 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2870 if (rsurface.texture->colormapping)
2871 permutation |= SHADERPERMUTATION_COLORMAPPING;
2872 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2873 permutation |= SHADERPERMUTATION_REFLECTION;
2874 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2875 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2877 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2879 // ambient model lighting
2880 mode = SHADERMODE_LIGHTDIRECTION;
2881 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2882 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2883 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2884 permutation |= SHADERPERMUTATION_GLOW;
2885 if (r_refdef.fogenabled)
2886 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2887 if (rsurface.texture->colormapping)
2888 permutation |= SHADERPERMUTATION_COLORMAPPING;
2889 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2890 permutation |= SHADERPERMUTATION_REFLECTION;
2891 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2892 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2897 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2899 // deluxemapping (light direction texture)
2900 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2901 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2903 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2904 permutation |= SHADERPERMUTATION_DIFFUSE;
2905 if (specularscale > 0)
2906 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2908 else if (r_glsl_deluxemapping.integer >= 2)
2910 // fake deluxemapping (uniform light direction in tangentspace)
2911 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2912 permutation |= SHADERPERMUTATION_DIFFUSE;
2913 if (specularscale > 0)
2914 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2916 else if (rsurface.uselightmaptexture)
2918 // ordinary lightmapping (q1bsp, q3bsp)
2919 mode = SHADERMODE_LIGHTMAP;
2923 // ordinary vertex coloring (q3bsp)
2924 mode = SHADERMODE_VERTEXCOLOR;
2926 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2927 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2928 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2929 permutation |= SHADERPERMUTATION_GLOW;
2930 if (r_refdef.fogenabled)
2931 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
2932 if (rsurface.texture->colormapping)
2933 permutation |= SHADERPERMUTATION_COLORMAPPING;
2934 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2935 permutation |= SHADERPERMUTATION_REFLECTION;
2936 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2937 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2939 if(permutation & SHADERPERMUTATION_SPECULAR)
2940 if(r_shadow_glossexact.integer)
2941 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2942 if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
2943 permutation |= SHADERPERMUTATION_ALPHAKILL;
2944 switch(vid.renderpath)
2946 case RENDERPATH_GL20:
2947 R_SetupShader_SetPermutationGLSL(mode, permutation);
2948 if (mode == SHADERMODE_LIGHTSOURCE)
2950 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2951 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2952 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2953 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);
2954 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);
2955 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
2957 // additive passes are only darkened by fog, not tinted
2958 if (r_glsl_permutation->loc_FogColor >= 0)
2959 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2960 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]);
2961 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]);
2962 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
2966 if (mode == SHADERMODE_FLATCOLOR)
2968 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
2970 else if (mode == SHADERMODE_LIGHTDIRECTION)
2972 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]);
2973 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
2974 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);
2975 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);
2976 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);
2977 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]);
2978 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]);
2982 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]);
2983 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]);
2984 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);
2985 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);
2986 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);
2988 // additive passes are only darkened by fog, not tinted
2989 if (r_glsl_permutation->loc_FogColor >= 0)
2991 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2992 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2994 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2996 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);
2997 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]);
2998 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]);
2999 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
3000 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
3001 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3002 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
3003 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3005 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3006 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
3007 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
3008 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3009 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
3010 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3011 if (r_glsl_permutation->loc_Color_Pants >= 0)
3013 if (rsurface.texture->pantstexture)
3014 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3016 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
3018 if (r_glsl_permutation->loc_Color_Shirt >= 0)
3020 if (rsurface.texture->shirttexture)
3021 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3023 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
3025 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]);
3026 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
3027 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
3028 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
3029 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
3030 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]);
3032 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(r_texture_white ));
3033 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , R_GetTexture(r_texture_white ));
3034 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , R_GetTexture(r_texture_gammaramps ));
3035 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , R_GetTexture(rsurface.texture->nmaptexture ));
3036 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , R_GetTexture(rsurface.texture->basetexture ));
3037 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , R_GetTexture(rsurface.texture->glosstexture ));
3038 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , R_GetTexture(rsurface.texture->glowtexture ));
3039 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , R_GetTexture(rsurface.texture->backgroundnmaptexture ));
3040 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , R_GetTexture(rsurface.texture->backgroundbasetexture ));
3041 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , R_GetTexture(rsurface.texture->backgroundglosstexture ));
3042 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , R_GetTexture(rsurface.texture->backgroundglowtexture ));
3043 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , R_GetTexture(rsurface.texture->pantstexture ));
3044 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , R_GetTexture(rsurface.texture->shirttexture ));
3045 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , R_GetTexture(r_texture_fogattenuation ));
3046 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(r_texture_white ));
3047 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(r_texture_blanknormalmap ));
3048 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , R_GetTexture(r_shadow_attenuationgradienttexture ));
3049 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , R_GetTexture(r_texture_white ));
3050 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , R_GetTexture(r_texture_white ));
3051 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture ));
3052 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture ));
3053 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDIFFUSE , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingdiffusetexture ));
3054 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBindAll(GL20TU_SCREENSPECULAR , 0, 0, 0, R_GetTexture(r_shadow_prepasslightingspeculartexture ));
3055 if (rsurface.rtlight)
3057 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBindAll(GL20TU_CUBE , 0, 0, R_GetTexture(rsurface.rtlight->currentcubemap ), 0);
3058 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture ));
3059 if (r_shadow_usingshadowmapcube)
3060 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE , 0, 0, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
3061 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , R_GetTexture(r_shadow_shadowmap2dtexture ));
3062 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0, R_GetTexture(r_shadow_shadowmapvsdcttexture ), 0);
3066 case RENDERPATH_CGGL:
3068 R_SetupShader_SetPermutationGLSL(mode, permutation);
3069 if (mode == SHADERMODE_LIGHTSOURCE)
3071 if (r_cg_permutation->vp_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}
3072 if (r_cg_permutation->vp_LightPosition >= 0) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
3076 if (mode == SHADERMODE_LIGHTDIRECTION)
3078 if (r_cg_permutation->vp_LightDir >= 0) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
3081 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);
3082 if (r_cg_permutation->vp_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}
3083 if (r_cg_permutation->vp_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}
3084 if (r_cg_permutation->vp_EyePosition >= 0) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3085 if (r_cg_permutation->vp_FogPlane >= 0) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3088 if (mode == SHADERMODE_LIGHTSOURCE)
3090 if (r_cg_permutation->fp_LightPosition >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
3091 if (r_cg_permutation->fp_LightColor >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
3092 if (r_cg_permutation->fp_Color_Ambient >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
3093 if (r_cg_permutation->fp_Color_Diffuse >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
3094 if (r_cg_permutation->fp_Color_Specular >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);
3096 // additive passes are only darkened by fog, not tinted
3097 if (r_cg_permutation->fp_FogColor >= 0)
3098 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
3099 if (r_cg_permutation->fp_ShadowMap_TextureScale >= 0) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3100 if (r_cg_permutation->fp_ShadowMap_Parameters >= 0) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3101 if (r_cg_permutation->fp_SpecularPower >= 0) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3105 if (mode == SHADERMODE_FLATCOLOR)
3107 if (r_cg_permutation->fp_Color_Ambient >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
3109 else if (mode == SHADERMODE_LIGHTDIRECTION)
3111 if (r_cg_permutation->fp_Color_Ambient >= 0) cgGLSetParameter3f(r_cg_permutation->fp_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]);
3112 if (r_cg_permutation->fp_Color_Diffuse >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
3113 if (r_cg_permutation->fp_Color_Specular >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
3114 if (r_cg_permutation->fp_DeferredMod_Diffuse >= 0) cgGLSetParameter3f(r_cg_permutation->fp_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);
3115 if (r_cg_permutation->fp_DeferredMod_Specular >= 0) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
3116 if (r_cg_permutation->fp_LightColor >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
3117 if (r_cg_permutation->fp_LightDir >= 0) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
3121 if (r_cg_permutation->fp_Color_Ambient >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
3122 if (r_cg_permutation->fp_Color_Diffuse >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
3123 if (r_cg_permutation->fp_Color_Specular >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
3124 if (r_cg_permutation->fp_DeferredMod_Diffuse >= 0) cgGLSetParameter3f(r_cg_permutation->fp_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);
3125 if (r_cg_permutation->fp_DeferredMod_Specular >= 0) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
3127 // additive passes are only darkened by fog, not tinted
3128 if (r_cg_permutation->fp_FogColor >= 0)
3130 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
3131 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
3133 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
3135 if (r_cg_permutation->fp_DistortScaleRefractReflect >= 0) cgGLSetParameter4f(r_cg_permutation->fp_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);
3136 if (r_cg_permutation->fp_ScreenScaleRefractReflect >= 0) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
3137 if (r_cg_permutation->fp_ScreenCenterRefractReflect >= 0) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
3138 if (r_cg_permutation->fp_RefractColor >= 0) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);
3139 if (r_cg_permutation->fp_ReflectColor >= 0) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);
3140 if (r_cg_permutation->fp_ReflectFactor >= 0) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3141 if (r_cg_permutation->fp_ReflectOffset >= 0) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);
3142 if (r_cg_permutation->fp_SpecularPower >= 0) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3144 if (r_cg_permutation->fp_Color_Glow >= 0) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3145 if (r_cg_permutation->fp_Alpha >= 0) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);
3146 if (r_cg_permutation->fp_EyePosition >= 0) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3147 if (r_cg_permutation->fp_Color_Pants >= 0)
3149 if (rsurface.texture->pantstexture)
3150 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3152 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
3154 if (r_cg_permutation->fp_Color_Shirt >= 0)
3156 if (rsurface.texture->shirttexture)
3157 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3159 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
3161 if (r_cg_permutation->fp_FogPlane >= 0) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3162 if (r_cg_permutation->fp_FogPlaneViewDist >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);
3163 if (r_cg_permutation->fp_FogRangeRecip >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);
3164 if (r_cg_permutation->fp_FogHeightFade >= 0) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);
3165 if (r_cg_permutation->fp_OffsetMapping_Scale >= 0) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
3166 if (r_cg_permutation->fp_ScreenToDepth >= 0) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3168 // if (r_cg_permutation->fp_Texture_First ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First , R_GetTexture(r_texture_white ));
3169 // if (r_cg_permutation->fp_Texture_Second ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second , R_GetTexture(r_texture_white ));
3170 // if (r_cg_permutation->fp_Texture_GammaRamps ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_GammaRamps , R_GetTexture(r_texture_gammaramps ));
3171 if (r_cg_permutation->fp_Texture_Normal ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Normal , R_GetTexture(rsurface.texture->nmaptexture ));
3172 if (r_cg_permutation->fp_Texture_Color ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Color , R_GetTexture(rsurface.texture->basetexture ));
3173 if (r_cg_permutation->fp_Texture_Gloss ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Gloss , R_GetTexture(rsurface.texture->glosstexture ));
3174 if (r_cg_permutation->fp_Texture_Glow ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Glow , R_GetTexture(rsurface.texture->glowtexture ));
3175 if (r_cg_permutation->fp_Texture_SecondaryNormal) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryNormal, R_GetTexture(rsurface.texture->backgroundnmaptexture ));
3176 if (r_cg_permutation->fp_Texture_SecondaryColor ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryColor , R_GetTexture(rsurface.texture->backgroundbasetexture ));
3177 if (r_cg_permutation->fp_Texture_SecondaryGloss ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryGloss , R_GetTexture(rsurface.texture->backgroundglosstexture ));
3178 if (r_cg_permutation->fp_Texture_SecondaryGlow ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_SecondaryGlow , R_GetTexture(rsurface.texture->backgroundglowtexture ));
3179 if (r_cg_permutation->fp_Texture_Pants ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Pants , R_GetTexture(rsurface.texture->pantstexture ));
3180 if (r_cg_permutation->fp_Texture_Shirt ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Shirt , R_GetTexture(rsurface.texture->shirttexture ));
3181 if (r_cg_permutation->fp_Texture_FogMask ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_FogMask , R_GetTexture(r_texture_fogattenuation ));
3182 if (r_cg_permutation->fp_Texture_Lightmap ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Lightmap , R_GetTexture(r_texture_white ));
3183 if (r_cg_permutation->fp_Texture_Deluxemap ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Deluxemap , R_GetTexture(r_texture_blanknormalmap ));
3184 if (r_cg_permutation->fp_Texture_Attenuation ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Attenuation , R_GetTexture(r_shadow_attenuationgradienttexture ));
3185 if (r_cg_permutation->fp_Texture_Refraction ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Refraction , R_GetTexture(r_texture_white ));
3186 if (r_cg_permutation->fp_Texture_Reflection ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Reflection , R_GetTexture(r_texture_white ));
3187 if (r_cg_permutation->fp_Texture_ScreenDepth ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDepth , R_GetTexture(r_shadow_prepassgeometrydepthtexture ));
3188 if (r_cg_permutation->fp_Texture_ScreenNormalMap) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture ));
3189 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDiffuse , R_GetTexture(r_shadow_prepasslightingdiffusetexture ));
3190 if (r_cg_permutation->fp_Texture_ScreenSpecular ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenSpecular , R_GetTexture(r_shadow_prepasslightingspeculartexture ));
3191 if (rsurface.rtlight)
3193 if (r_cg_permutation->fp_Texture_Cube ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Cube , R_GetTexture(rsurface.rtlight->currentcubemap ));
3194 if (r_cg_permutation->fp_Texture_ShadowMapRect ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapRect , R_GetTexture(r_shadow_shadowmaprectangletexture ));
3195 if (r_shadow_usingshadowmapcube)
3196 if (r_cg_permutation->fp_Texture_ShadowMapCube ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapCube , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
3197 if (r_cg_permutation->fp_Texture_ShadowMap2D ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMap2D , R_GetTexture(r_shadow_shadowmap2dtexture ));
3198 if (r_cg_permutation->fp_Texture_CubeProjection ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture ));
3204 case RENDERPATH_GL13:
3205 case RENDERPATH_GL11:
3210 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3212 // select a permutation of the lighting shader appropriate to this
3213 // combination of texture, entity, light source, and fogging, only use the
3214 // minimum features necessary to avoid wasting rendering time in the
3215 // fragment shader on features that are not being used
3216 unsigned int permutation = 0;
3217 unsigned int mode = 0;
3218 const float *lightcolorbase = rtlight->currentcolor;
3219 float ambientscale = rtlight->ambientscale;
3220 float diffusescale = rtlight->diffusescale;
3221 float specularscale = rtlight->specularscale;
3222 // this is the location of the light in view space
3223 vec3_t viewlightorigin;
3224 // this transforms from view space (camera) to light space (cubemap)
3225 matrix4x4_t viewtolight;
3226 matrix4x4_t lighttoview;
3227 float viewtolight16f[16];
3228 float range = 1.0f / r_shadow_deferred_8bitrange.value;
3230 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3231 if (rtlight->currentcubemap != r_texture_whitecube)
3232 permutation |= SHADERPERMUTATION_CUBEFILTER;
3233 if (diffusescale > 0)
3234 permutation |= SHADERPERMUTATION_DIFFUSE;
3235 if (specularscale > 0)
3237 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3238 if (r_shadow_glossexact.integer)
3239 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
3241 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
3243 if (r_shadow_usingshadowmaprect)
3244 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
3245 if (r_shadow_usingshadowmap2d)
3246 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3247 if (r_shadow_usingshadowmapcube)
3248 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
3249 else if(r_shadow_shadowmapvsdct)
3250 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3252 if (r_shadow_shadowmapsampler)
3253 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3254 if (r_shadow_shadowmappcf > 1)
3255 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3256 else if (r_shadow_shadowmappcf)
3257 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3259 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3260 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3261 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3262 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3263 switch(vid.renderpath)
3265 case RENDERPATH_GL20:
3266 R_SetupShader_SetPermutationGLSL(mode, permutation);
3267 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3268 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3269 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3270 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);
3271 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);
3272 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);
3273 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]);
3274 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]);
3275 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));
3276 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]);
3278 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , R_GetTexture(r_shadow_attenuationgradienttexture ));
3279 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBindAll(GL20TU_SCREENDEPTH , 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrydepthtexture ));
3280 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBindAll(GL20TU_SCREENNORMALMAP, 0, 0, 0, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture ));
3281 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBindAll(GL20TU_CUBE , 0, 0, R_GetTexture(rsurface.rtlight->currentcubemap ), 0);
3282 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPRECT , 0, 0, 0, R_GetTexture(r_shadow_shadowmaprectangletexture ));
3283 if (r_shadow_usingshadowmapcube)
3284 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBindAll(GL20TU_SHADOWMAPCUBE , 0, 0, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);
3285 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , R_GetTexture(r_shadow_shadowmap2dtexture ));
3286 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBindAll(GL20TU_CUBEPROJECTION , 0, 0, R_GetTexture(r_shadow_shadowmapvsdcttexture ), 0);
3288 case RENDERPATH_CGGL:
3290 R_SetupShader_SetPermutationCG(mode, permutation);
3291 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);
3292 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3293 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);
3294 if (r_cg_permutation->fp_DeferredColor_Ambient ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3295 if (r_cg_permutation->fp_DeferredColor_Diffuse ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3296 if (r_cg_permutation->fp_DeferredColor_Specular ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3297 if (r_cg_permutation->fp_ShadowMap_TextureScale ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3298 if (r_cg_permutation->fp_ShadowMap_Parameters ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3299 if (r_cg_permutation->fp_SpecularPower ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
3300 if (r_cg_permutation->fp_ScreenToDepth ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3302 if (r_cg_permutation->fp_Texture_Attenuation ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Attenuation , R_GetTexture(r_shadow_attenuationgradienttexture ));
3303 if (r_cg_permutation->fp_Texture_ScreenDepth ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenDepth , R_GetTexture(r_shadow_prepassgeometrydepthtexture ));
3304 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ScreenNormalMap, R_GetTexture(r_shadow_prepassgeometrynormalmaptexture ));
3305 if (r_cg_permutation->fp_Texture_Cube ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Cube , R_GetTexture(rsurface.rtlight->currentcubemap ));
3306 if (r_cg_permutation->fp_Texture_ShadowMapRect ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapRect , R_GetTexture(r_shadow_shadowmaprectangletexture ));
3307 if (r_shadow_usingshadowmapcube)
3308 if (r_cg_permutation->fp_Texture_ShadowMapCube ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMapCube , R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]));
3309 if (r_cg_permutation->fp_Texture_ShadowMap2D ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_ShadowMap2D , R_GetTexture(r_shadow_shadowmap2dtexture ));
3310 if (r_cg_permutation->fp_Texture_CubeProjection ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_CubeProjection , R_GetTexture(r_shadow_shadowmapvsdcttexture ));
3313 case RENDERPATH_GL13:
3314 case RENDERPATH_GL11:
3319 #define SKINFRAME_HASH 1024
3323 int loadsequence; // incremented each level change
3324 memexpandablearray_t array;
3325 skinframe_t *hash[SKINFRAME_HASH];
3328 r_skinframe_t r_skinframe;
3330 void R_SkinFrame_PrepareForPurge(void)
3332 r_skinframe.loadsequence++;
3333 // wrap it without hitting zero
3334 if (r_skinframe.loadsequence >= 200)
3335 r_skinframe.loadsequence = 1;
3338 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3342 // mark the skinframe as used for the purging code
3343 skinframe->loadsequence = r_skinframe.loadsequence;
3346 void R_SkinFrame_Purge(void)
3350 for (i = 0;i < SKINFRAME_HASH;i++)
3352 for (s = r_skinframe.hash[i];s;s = s->next)
3354 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3356 if (s->merged == s->base)
3358 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3359 R_PurgeTexture(s->stain );s->stain = NULL;
3360 R_PurgeTexture(s->merged);s->merged = NULL;
3361 R_PurgeTexture(s->base );s->base = NULL;
3362 R_PurgeTexture(s->pants );s->pants = NULL;
3363 R_PurgeTexture(s->shirt );s->shirt = NULL;
3364 R_PurgeTexture(s->nmap );s->nmap = NULL;
3365 R_PurgeTexture(s->gloss );s->gloss = NULL;
3366 R_PurgeTexture(s->glow );s->glow = NULL;
3367 R_PurgeTexture(s->fog );s->fog = NULL;
3368 s->loadsequence = 0;
3374 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3376 char basename[MAX_QPATH];
3378 Image_StripImageExtension(name, basename, sizeof(basename));
3380 if( last == NULL ) {
3382 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3383 item = r_skinframe.hash[hashindex];
3388 // linearly search through the hash bucket
3389 for( ; item ; item = item->next ) {
3390 if( !strcmp( item->basename, basename ) ) {
3397 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3401 char basename[MAX_QPATH];
3403 Image_StripImageExtension(name, basename, sizeof(basename));
3405 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3406 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3407 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3411 rtexture_t *dyntexture;
3412 // check whether its a dynamic texture
3413 dyntexture = CL_GetDynTexture( basename );
3414 if (!add && !dyntexture)
3416 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3417 memset(item, 0, sizeof(*item));
3418 strlcpy(item->basename, basename, sizeof(item->basename));
3419 item->base = dyntexture; // either NULL or dyntexture handle
3420 item->textureflags = textureflags;
3421 item->comparewidth = comparewidth;
3422 item->compareheight = compareheight;
3423 item->comparecrc = comparecrc;
3424 item->next = r_skinframe.hash[hashindex];
3425 r_skinframe.hash[hashindex] = item;
3427 else if( item->base == NULL )
3429 rtexture_t *dyntexture;
3430 // check whether its a dynamic texture
3431 // 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]
3432 dyntexture = CL_GetDynTexture( basename );
3433 item->base = dyntexture; // either NULL or dyntexture handle
3436 R_SkinFrame_MarkUsed(item);
3440 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3442 unsigned long long avgcolor[5], wsum; \
3450 for(pix = 0; pix < cnt; ++pix) \
3453 for(comp = 0; comp < 3; ++comp) \
3455 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3458 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3460 for(comp = 0; comp < 3; ++comp) \
3461 avgcolor[comp] += getpixel * w; \
3464 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3465 avgcolor[4] += getpixel; \
3467 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3469 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3470 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3471 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3472 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3475 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3478 unsigned char *pixels;
3479 unsigned char *bumppixels;
3480 unsigned char *basepixels = NULL;
3481 int basepixels_width;
3482 int basepixels_height;
3483 skinframe_t *skinframe;
3485 if (cls.state == ca_dedicated)
3488 // return an existing skinframe if already loaded
3489 // if loading of the first image fails, don't make a new skinframe as it
3490 // would cause all future lookups of this to be missing
3491 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3492 if (skinframe && skinframe->base)
3495 basepixels = loadimagepixelsbgra(name, complain, true);
3496 if (basepixels == NULL)
3499 if (developer_loading.integer)
3500 Con_Printf("loading skin \"%s\"\n", name);
3502 // we've got some pixels to store, so really allocate this new texture now
3504 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3505 skinframe->stain = NULL;
3506 skinframe->merged = NULL;
3507 skinframe->base = r_texture_notexture;
3508 skinframe->pants = NULL;
3509 skinframe->shirt = NULL;
3510 skinframe->nmap = r_texture_blanknormalmap;
3511 skinframe->gloss = NULL;
3512 skinframe->glow = NULL;
3513 skinframe->fog = NULL;
3514 skinframe->hasalpha = false;
3516 basepixels_width = image_width;
3517 basepixels_height = image_height;
3518 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);
3520 if (textureflags & TEXF_ALPHA)
3522 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3524 if (basepixels[j] < 255)
3526 skinframe->hasalpha = true;
3530 if (r_loadfog && skinframe->hasalpha)
3532 // has transparent pixels
3533 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3534 for (j = 0;j < image_width * image_height * 4;j += 4)
3539 pixels[j+3] = basepixels[j+3];
3541 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);
3546 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3547 //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]);
3549 // _norm is the name used by tenebrae and has been adopted as standard
3550 if (r_loadnormalmap)
3552 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
3554 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);
3558 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
3560 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3561 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3562 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);
3564 Mem_Free(bumppixels);
3566 else if (r_shadow_bumpscale_basetexture.value > 0)
3568 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3569 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3570 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);
3574 // _luma is supported for tenebrae compatibility
3575 // (I think it's a very stupid name, but oh well)
3576 // _glow is the preferred name
3577 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;}
3578 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;}
3579 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;}
3580 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;}
3583 Mem_Free(basepixels);
3588 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3589 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3592 unsigned char *temp1, *temp2;
3593 skinframe_t *skinframe;
3595 if (cls.state == ca_dedicated)
3598 // if already loaded just return it, otherwise make a new skinframe
3599 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3600 if (skinframe && skinframe->base)
3603 skinframe->stain = NULL;
3604 skinframe->merged = NULL;
3605 skinframe->base = r_texture_notexture;
3606 skinframe->pants = NULL;
3607 skinframe->shirt = NULL;
3608 skinframe->nmap = r_texture_blanknormalmap;
3609 skinframe->gloss = NULL;
3610 skinframe->glow = NULL;
3611 skinframe->fog = NULL;
3612 skinframe->hasalpha = false;
3614 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3618 if (developer_loading.integer)
3619 Con_Printf("loading 32bit skin \"%s\"\n", name);
3621 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3623 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3624 temp2 = temp1 + width * height * 4;
3625 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3626 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3629 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
3630 if (textureflags & TEXF_ALPHA)
3632 for (i = 3;i < width * height * 4;i += 4)
3634 if (skindata[i] < 255)
3636 skinframe->hasalpha = true;
3640 if (r_loadfog && skinframe->hasalpha)
3642 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3643 memcpy(fogpixels, skindata, width * height * 4);
3644 for (i = 0;i < width * height * 4;i += 4)
3645 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3646 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
3647 Mem_Free(fogpixels);
3651 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3652 //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]);
3657 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3661 skinframe_t *skinframe;
3663 if (cls.state == ca_dedicated)
3666 // if already loaded just return it, otherwise make a new skinframe
3667 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3668 if (skinframe && skinframe->base)
3671 skinframe->stain = NULL;
3672 skinframe->merged = NULL;
3673 skinframe->base = r_texture_notexture;
3674 skinframe->pants = NULL;
3675 skinframe->shirt = NULL;
3676 skinframe->nmap = r_texture_blanknormalmap;
3677 skinframe->gloss = NULL;
3678 skinframe->glow = NULL;
3679 skinframe->fog = NULL;
3680 skinframe->hasalpha = false;
3682 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3686 if (developer_loading.integer)
3687 Con_Printf("loading quake skin \"%s\"\n", name);
3689 // 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)
3690 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
3691 memcpy(skinframe->qpixels, skindata, width*height);
3692 skinframe->qwidth = width;
3693 skinframe->qheight = height;
3696 for (i = 0;i < width * height;i++)
3697 featuresmask |= palette_featureflags[skindata[i]];
3699 skinframe->hasalpha = false;
3700 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3701 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3702 skinframe->qgeneratemerged = true;
3703 skinframe->qgeneratebase = skinframe->qhascolormapping;
3704 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3706 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3707 //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]);
3712 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3716 unsigned char *skindata;
3718 if (!skinframe->qpixels)
3721 if (!skinframe->qhascolormapping)
3722 colormapped = false;
3726 if (!skinframe->qgeneratebase)
3731 if (!skinframe->qgeneratemerged)
3735 width = skinframe->qwidth;
3736 height = skinframe->qheight;
3737 skindata = skinframe->qpixels;
3739 if (skinframe->qgeneratenmap)
3741 unsigned char *temp1, *temp2;
3742 skinframe->qgeneratenmap = false;
3743 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3744 temp2 = temp1 + width * height * 4;
3745 // use either a custom palette or the quake palette
3746 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3747 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3748 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
3752 if (skinframe->qgenerateglow)
3754 skinframe->qgenerateglow = false;
3755 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
3760 skinframe->qgeneratebase = false;
3761 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);
3762 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
3763 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
3767 skinframe->qgeneratemerged = false;
3768 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3771 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3773 Mem_Free(skinframe->qpixels);
3774 skinframe->qpixels = NULL;
3778 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)
3781 skinframe_t *skinframe;
3783 if (cls.state == ca_dedicated)
3786 // if already loaded just return it, otherwise make a new skinframe
3787 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3788 if (skinframe && skinframe->base)
3791 skinframe->stain = NULL;
3792 skinframe->merged = NULL;
3793 skinframe->base = r_texture_notexture;
3794 skinframe->pants = NULL;
3795 skinframe->shirt = NULL;
3796 skinframe->nmap = r_texture_blanknormalmap;
3797 skinframe->gloss = NULL;
3798 skinframe->glow = NULL;
3799 skinframe->fog = NULL;
3800 skinframe->hasalpha = false;
3802 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3806 if (developer_loading.integer)
3807 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3809 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
3810 if (textureflags & TEXF_ALPHA)
3812 for (i = 0;i < width * height;i++)
3814 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3816 skinframe->hasalpha = true;
3820 if (r_loadfog && skinframe->hasalpha)
3821 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
3824 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3825 //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]);
3830 skinframe_t *R_SkinFrame_LoadMissing(void)
3832 skinframe_t *skinframe;
3834 if (cls.state == ca_dedicated)
3837 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3838 skinframe->stain = NULL;
3839 skinframe->merged = NULL;
3840 skinframe->base = r_texture_notexture;
3841 skinframe->pants = NULL;
3842 skinframe->shirt = NULL;
3843 skinframe->nmap = r_texture_blanknormalmap;
3844 skinframe->gloss = NULL;
3845 skinframe->glow = NULL;
3846 skinframe->fog = NULL;
3847 skinframe->hasalpha = false;
3849 skinframe->avgcolor[0] = rand() / RAND_MAX;
3850 skinframe->avgcolor[1] = rand() / RAND_MAX;
3851 skinframe->avgcolor[2] = rand() / RAND_MAX;
3852 skinframe->avgcolor[3] = 1;
3857 void R_Main_FreeViewCache(void)
3859 if (r_refdef.viewcache.entityvisible)
3860 Mem_Free(r_refdef.viewcache.entityvisible);
3861 if (r_refdef.viewcache.world_pvsbits)
3862 Mem_Free(r_refdef.viewcache.world_pvsbits);
3863 if (r_refdef.viewcache.world_leafvisible)
3864 Mem_Free(r_refdef.viewcache.world_leafvisible);
3865 if (r_refdef.viewcache.world_surfacevisible)
3866 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3867 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3870 void R_Main_ResizeViewCache(void)
3872 int numentities = r_refdef.scene.numentities;
3873 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3874 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3875 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3876 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3877 if (r_refdef.viewcache.maxentities < numentities)
3879 r_refdef.viewcache.maxentities = numentities;
3880 if (r_refdef.viewcache.entityvisible)
3881 Mem_Free(r_refdef.viewcache.entityvisible);
3882 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3884 if (r_refdef.viewcache.world_numclusters != numclusters)
3886 r_refdef.viewcache.world_numclusters = numclusters;
3887 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3888 if (r_refdef.viewcache.world_pvsbits)
3889 Mem_Free(r_refdef.viewcache.world_pvsbits);
3890 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3892 if (r_refdef.viewcache.world_numleafs != numleafs)
3894 r_refdef.viewcache.world_numleafs = numleafs;
3895 if (r_refdef.viewcache.world_leafvisible)
3896 Mem_Free(r_refdef.viewcache.world_leafvisible);
3897 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3899 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3901 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3902 if (r_refdef.viewcache.world_surfacevisible)
3903 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3904 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3908 extern rtexture_t *loadingscreentexture;
3909 void gl_main_start(void)
3911 loadingscreentexture = NULL;
3912 r_texture_blanknormalmap = NULL;
3913 r_texture_white = NULL;
3914 r_texture_grey128 = NULL;
3915 r_texture_black = NULL;
3916 r_texture_whitecube = NULL;
3917 r_texture_normalizationcube = NULL;
3918 r_texture_fogattenuation = NULL;
3919 r_texture_gammaramps = NULL;
3921 switch(vid.renderpath)
3923 case RENDERPATH_GL20:
3924 case RENDERPATH_CGGL:
3925 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3926 Cvar_SetValueQuick(&gl_combine, 1);
3927 Cvar_SetValueQuick(&r_glsl, 1);
3928 r_loadnormalmap = true;
3932 case RENDERPATH_GL13:
3933 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3934 Cvar_SetValueQuick(&gl_combine, 1);
3935 Cvar_SetValueQuick(&r_glsl, 0);
3936 r_loadnormalmap = false;
3937 r_loadgloss = false;
3940 case RENDERPATH_GL11:
3941 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3942 Cvar_SetValueQuick(&gl_combine, 0);
3943 Cvar_SetValueQuick(&r_glsl, 0);
3944 r_loadnormalmap = false;
3945 r_loadgloss = false;
3951 R_FrameData_Reset();
3955 memset(r_queries, 0, sizeof(r_queries));
3957 r_qwskincache = NULL;
3958 r_qwskincache_size = 0;
3960 // set up r_skinframe loading system for textures
3961 memset(&r_skinframe, 0, sizeof(r_skinframe));
3962 r_skinframe.loadsequence = 1;
3963 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3965 r_main_texturepool = R_AllocTexturePool();
3966 R_BuildBlankTextures();
3968 if (vid.support.arb_texture_cube_map)
3971 R_BuildNormalizationCube();
3973 r_texture_fogattenuation = NULL;
3974 r_texture_gammaramps = NULL;
3975 //r_texture_fogintensity = NULL;
3976 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3977 memset(&r_waterstate, 0, sizeof(r_waterstate));
3978 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3979 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3981 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
3982 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
3984 memset(&r_svbsp, 0, sizeof (r_svbsp));
3986 r_refdef.fogmasktable_density = 0;
3989 void gl_main_shutdown(void)
3992 R_FrameData_Reset();
3994 R_Main_FreeViewCache();
3997 qglDeleteQueriesARB(r_maxqueries, r_queries);
4001 memset(r_queries, 0, sizeof(r_queries));
4003 r_qwskincache = NULL;
4004 r_qwskincache_size = 0;
4006 // clear out the r_skinframe state
4007 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4008 memset(&r_skinframe, 0, sizeof(r_skinframe));
4011 Mem_Free(r_svbsp.nodes);
4012 memset(&r_svbsp, 0, sizeof (r_svbsp));
4013 R_FreeTexturePool(&r_main_texturepool);
4014 loadingscreentexture = NULL;
4015 r_texture_blanknormalmap = NULL;
4016 r_texture_white = NULL;
4017 r_texture_grey128 = NULL;
4018 r_texture_black = NULL;
4019 r_texture_whitecube = NULL;
4020 r_texture_normalizationcube = NULL;
4021 r_texture_fogattenuation = NULL;
4022 r_texture_gammaramps = NULL;
4023 //r_texture_fogintensity = NULL;
4024 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4025 memset(&r_waterstate, 0, sizeof(r_waterstate));
4029 extern void CL_ParseEntityLump(char *entitystring);
4030 void gl_main_newmap(void)
4032 // FIXME: move this code to client
4034 char *entities, entname[MAX_QPATH];
4036 Mem_Free(r_qwskincache);
4037 r_qwskincache = NULL;
4038 r_qwskincache_size = 0;
4041 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
4042 l = (int)strlen(entname) - 4;
4043 if (l >= 0 && !strcmp(entname + l, ".bsp"))
4045 memcpy(entname + l, ".ent", 5);
4046 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4048 CL_ParseEntityLump(entities);
4053 if (cl.worldmodel->brush.entities)
4054 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4056 R_Main_FreeViewCache();
4058 R_FrameData_Reset();
4061 void GL_Main_Init(void)
4063 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4065 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4066 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4067 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4068 if (gamemode == GAME_NEHAHRA)
4070 Cvar_RegisterVariable (&gl_fogenable);
4071 Cvar_RegisterVariable (&gl_fogdensity);
4072 Cvar_RegisterVariable (&gl_fogred);
4073 Cvar_RegisterVariable (&gl_foggreen);
4074 Cvar_RegisterVariable (&gl_fogblue);
4075 Cvar_RegisterVariable (&gl_fogstart);
4076 Cvar_RegisterVariable (&gl_fogend);
4077 Cvar_RegisterVariable (&gl_skyclip);
4079 Cvar_RegisterVariable(&r_motionblur);
4080 Cvar_RegisterVariable(&r_motionblur_maxblur);
4081 Cvar_RegisterVariable(&r_motionblur_bmin);
4082 Cvar_RegisterVariable(&r_motionblur_vmin);
4083 Cvar_RegisterVariable(&r_motionblur_vmax);
4084 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4085 Cvar_RegisterVariable(&r_motionblur_randomize);
4086 Cvar_RegisterVariable(&r_damageblur);
4087 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4088 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4089 Cvar_RegisterVariable(&r_equalize_entities_by);
4090 Cvar_RegisterVariable(&r_equalize_entities_to);
4091 Cvar_RegisterVariable(&r_depthfirst);
4092 Cvar_RegisterVariable(&r_useinfinitefarclip);
4093 Cvar_RegisterVariable(&r_farclip_base);
4094 Cvar_RegisterVariable(&r_farclip_world);
4095 Cvar_RegisterVariable(&r_nearclip);
4096 Cvar_RegisterVariable(&r_showbboxes);
4097 Cvar_RegisterVariable(&r_showsurfaces);
4098 Cvar_RegisterVariable(&r_showtris);
4099 Cvar_RegisterVariable(&r_shownormals);
4100 Cvar_RegisterVariable(&r_showlighting);
4101 Cvar_RegisterVariable(&r_showshadowvolumes);
4102 Cvar_RegisterVariable(&r_showcollisionbrushes);
4103 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4104 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4105 Cvar_RegisterVariable(&r_showdisabledepthtest);
4106 Cvar_RegisterVariable(&r_drawportals);
4107 Cvar_RegisterVariable(&r_drawentities);
4108 Cvar_RegisterVariable(&r_cullentities_trace);
4109 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4110 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4111 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4112 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4113 Cvar_RegisterVariable(&r_drawviewmodel);
4114 Cvar_RegisterVariable(&r_speeds);
4115 Cvar_RegisterVariable(&r_fullbrights);
4116 Cvar_RegisterVariable(&r_wateralpha);
4117 Cvar_RegisterVariable(&r_dynamic);
4118 Cvar_RegisterVariable(&r_fullbright);
4119 Cvar_RegisterVariable(&r_shadows);
4120 Cvar_RegisterVariable(&r_shadows_darken);
4121 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4122 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4123 Cvar_RegisterVariable(&r_shadows_throwdistance);
4124 Cvar_RegisterVariable(&r_shadows_throwdirection);
4125 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4126 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4127 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4128 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4129 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4130 Cvar_RegisterVariable(&r_fog_exp2);
4131 Cvar_RegisterVariable(&r_drawfog);
4132 Cvar_RegisterVariable(&r_transparentdepthmasking);
4133 Cvar_RegisterVariable(&r_textureunits);
4134 Cvar_RegisterVariable(&gl_combine);
4135 Cvar_RegisterVariable(&r_glsl);
4136 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4137 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4138 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4139 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4140 Cvar_RegisterVariable(&r_glsl_postprocess);
4141 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4142 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4143 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4144 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4145 Cvar_RegisterVariable(&r_water);
4146 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4147 Cvar_RegisterVariable(&r_water_clippingplanebias);
4148 Cvar_RegisterVariable(&r_water_refractdistort);
4149 Cvar_RegisterVariable(&r_water_reflectdistort);
4150 Cvar_RegisterVariable(&r_lerpsprites);
4151 Cvar_RegisterVariable(&r_lerpmodels);
4152 Cvar_RegisterVariable(&r_lerplightstyles);
4153 Cvar_RegisterVariable(&r_waterscroll);
4154 Cvar_RegisterVariable(&r_bloom);
4155 Cvar_RegisterVariable(&r_bloom_colorscale);
4156 Cvar_RegisterVariable(&r_bloom_brighten);
4157 Cvar_RegisterVariable(&r_bloom_blur);
4158 Cvar_RegisterVariable(&r_bloom_resolution);
4159 Cvar_RegisterVariable(&r_bloom_colorexponent);
4160 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4161 Cvar_RegisterVariable(&r_hdr);
4162 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4163 Cvar_RegisterVariable(&r_hdr_glowintensity);
4164 Cvar_RegisterVariable(&r_hdr_range);
4165 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4166 Cvar_RegisterVariable(&developer_texturelogging);
4167 Cvar_RegisterVariable(&gl_lightmaps);
4168 Cvar_RegisterVariable(&r_test);
4169 Cvar_RegisterVariable(&r_batchmode);
4170 Cvar_RegisterVariable(&r_glsl_saturation);
4171 Cvar_RegisterVariable(&r_framedatasize);
4172 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4173 Cvar_SetValue("r_fullbrights", 0);
4174 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
4176 Cvar_RegisterVariable(&r_track_sprites);
4177 Cvar_RegisterVariable(&r_track_sprites_flags);
4178 Cvar_RegisterVariable(&r_track_sprites_scalew);
4179 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4182 extern void R_Textures_Init(void);
4183 extern void GL_Draw_Init(void);
4184 extern void GL_Main_Init(void);
4185 extern void R_Shadow_Init(void);
4186 extern void R_Sky_Init(void);
4187 extern void GL_Surf_Init(void);
4188 extern void R_Particles_Init(void);
4189 extern void R_Explosion_Init(void);
4190 extern void gl_backend_init(void);
4191 extern void Sbar_Init(void);
4192 extern void R_LightningBeams_Init(void);
4193 extern void Mod_RenderInit(void);
4195 void Render_Init(void)
4207 R_LightningBeams_Init();
4216 extern char *ENGINE_EXTENSIONS;
4219 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4220 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4221 gl_version = (const char *)qglGetString(GL_VERSION);
4222 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4226 if (!gl_platformextensions)
4227 gl_platformextensions = "";
4229 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4230 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4231 Con_Printf("GL_VERSION: %s\n", gl_version);
4232 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4233 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4235 VID_CheckExtensions();
4237 // LordHavoc: report supported extensions
4238 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4240 // clear to black (loading plaque will be seen over this)
4242 qglClearColor(0,0,0,1);CHECKGLERROR
4243 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
4246 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4250 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4252 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4255 p = r_refdef.view.frustum + i;
4260 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4264 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4268 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4272 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4276 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4280 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4284 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4288 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4296 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4300 for (i = 0;i < numplanes;i++)
4307 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4311 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4315 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4319 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4323 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4327 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4331 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4335 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4343 //==================================================================================
4345 // LordHavoc: this stores temporary data used within the same frame
4347 qboolean r_framedata_failed;
4348 static size_t r_framedata_size;
4349 static size_t r_framedata_current;
4350 static void *r_framedata_base;
4352 void R_FrameData_Reset(void)
4354 if (r_framedata_base);
4355 Mem_Free(r_framedata_base);
4356 r_framedata_base = NULL;
4357 r_framedata_size = 0;
4358 r_framedata_current = 0;
4359 r_framedata_failed = false;
4362 void R_FrameData_NewFrame(void)
4365 if (r_framedata_failed)
4366 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
4367 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4368 wantedsize = bound(65536, wantedsize, 128*1024*1024);
4369 if (r_framedata_size != wantedsize)
4371 r_framedata_size = wantedsize;
4372 if (r_framedata_base);
4373 Mem_Free(r_framedata_base);
4374 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
4376 r_framedata_current = 0;
4377 r_framedata_failed = false;
4380 void *R_FrameData_Alloc(size_t size)
4384 // align to 16 byte boundary
4385 size = (size + 15) & ~15;
4386 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
4387 r_framedata_current += size;
4390 if (r_framedata_current > r_framedata_size)
4391 r_framedata_failed = true;
4393 // return NULL on everything after a failure
4394 if (r_framedata_failed)
4400 void *R_FrameData_Store(size_t size, void *data)
4402 void *d = R_FrameData_Alloc(size);
4404 memcpy(d, data, size);
4408 //==================================================================================
4410 // LordHavoc: animcache originally written by Echon, rewritten since then
4413 * Animation cache prevents re-generating mesh data for an animated model
4414 * multiple times in one frame for lighting, shadowing, reflections, etc.
4417 void R_AnimCache_Free(void)
4421 void R_AnimCache_ClearCache(void)
4424 entity_render_t *ent;
4426 for (i = 0;i < r_refdef.scene.numentities;i++)
4428 ent = r_refdef.scene.entities[i];
4429 ent->animcache_vertex3f = NULL;
4430 ent->animcache_normal3f = NULL;
4431 ent->animcache_svector3f = NULL;
4432 ent->animcache_tvector3f = NULL;
4436 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4438 dp_model_t *model = ent->model;
4440 // see if it's already cached this frame
4441 if (ent->animcache_vertex3f)
4443 // add normals/tangents if needed
4444 if (wantnormals || wanttangents)
4446 if (ent->animcache_normal3f)
4447 wantnormals = false;
4448 if (ent->animcache_svector3f)
4449 wanttangents = false;
4450 if (wantnormals || wanttangents)
4452 numvertices = model->surfmesh.num_vertices;
4454 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4457 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4458 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4460 if (!r_framedata_failed)
4461 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4467 // see if this ent is worth caching
4468 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4470 // get some memory for this entity and generate mesh data
4471 numvertices = model->surfmesh.num_vertices;
4472 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4474 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4477 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4478 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
4480 if (!r_framedata_failed)
4481 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4483 return !r_framedata_failed;
4486 void R_AnimCache_CacheVisibleEntities(void)
4489 qboolean wantnormals = !r_showsurfaces.integer;
4490 qboolean wanttangents = !r_showsurfaces.integer;
4492 switch(vid.renderpath)
4494 case RENDERPATH_GL20:
4495 case RENDERPATH_CGGL:
4497 case RENDERPATH_GL13:
4498 case RENDERPATH_GL11:
4499 wanttangents = false;
4503 // TODO: thread this
4504 // NOTE: R_PrepareRTLights() also caches entities
4506 for (i = 0;i < r_refdef.scene.numentities;i++)
4507 if (r_refdef.viewcache.entityvisible[i])
4508 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4510 if (r_shadows.integer)
4511 for (i = 0;i < r_refdef.scene.numentities;i++)
4512 if (!r_refdef.viewcache.entityvisible[i])
4513 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
4516 //==================================================================================
4518 static void R_View_UpdateEntityLighting (void)
4521 entity_render_t *ent;
4522 vec3_t tempdiffusenormal, avg;
4523 vec_t f, fa, fd, fdd;
4525 for (i = 0;i < r_refdef.scene.numentities;i++)
4527 ent = r_refdef.scene.entities[i];
4529 // skip unseen models
4530 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
4534 if (ent->model && ent->model->brush.num_leafs)
4536 // TODO: use modellight for r_ambient settings on world?
4537 VectorSet(ent->modellight_ambient, 0, 0, 0);
4538 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4539 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4543 // fetch the lighting from the worldmodel data
4544 VectorClear(ent->modellight_ambient);
4545 VectorClear(ent->modellight_diffuse);
4546 VectorClear(tempdiffusenormal);
4547 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4550 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4551 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
4552 if(ent->flags & RENDER_EQUALIZE)
4554 // first fix up ambient lighting...
4555 if(r_equalize_entities_minambient.value > 0)
4557 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4560 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4561 if(fa < r_equalize_entities_minambient.value * fd)
4564 // fa'/fd' = minambient
4565 // fa'+0.25*fd' = fa+0.25*fd
4567 // fa' = fd' * minambient
4568 // fd'*(0.25+minambient) = fa+0.25*fd
4570 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4571 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4573 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4574 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
4575 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4576 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4581 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4583 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
4584 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
4587 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
4588 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
4589 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4595 VectorSet(ent->modellight_ambient, 1, 1, 1);
4597 // move the light direction into modelspace coordinates for lighting code
4598 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4599 if(VectorLength2(ent->modellight_lightdir) == 0)
4600 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4601 VectorNormalize(ent->modellight_lightdir);
4605 #define MAX_LINEOFSIGHTTRACES 64
4607 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4610 vec3_t boxmins, boxmaxs;
4613 dp_model_t *model = r_refdef.scene.worldmodel;
4615 if (!model || !model->brush.TraceLineOfSight)
4618 // expand the box a little
4619 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4620 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4621 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4622 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4623 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4624 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4627 VectorCopy(eye, start);
4628 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4629 if (model->brush.TraceLineOfSight(model, start, end))
4632 // try various random positions
4633 for (i = 0;i < numsamples;i++)
4635 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4636 if (model->brush.TraceLineOfSight(model, start, end))
4644 static void R_View_UpdateEntityVisible (void)
4649 entity_render_t *ent;
4651 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
4652 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4654 // worldmodel can check visibility
4655 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4656 for (i = 0;i < r_refdef.scene.numentities;i++)
4658 ent = r_refdef.scene.entities[i];
4659 if (!(ent->flags & renderimask))
4660 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)))
4661 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))
4662 r_refdef.viewcache.entityvisible[i] = true;
4664 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
4666 for (i = 0;i < r_refdef.scene.numentities;i++)
4668 ent = r_refdef.scene.entities[i];
4669 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4671 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4673 continue; // temp entities do pvs only
4674 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4675 ent->last_trace_visibility = realtime;
4676 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4677 r_refdef.viewcache.entityvisible[i] = 0;
4684 // no worldmodel or it can't check visibility
4685 for (i = 0;i < r_refdef.scene.numentities;i++)
4687 ent = r_refdef.scene.entities[i];
4688 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));
4693 /// only used if skyrendermasked, and normally returns false
4694 int R_DrawBrushModelsSky (void)
4697 entity_render_t *ent;
4700 for (i = 0;i < r_refdef.scene.numentities;i++)
4702 if (!r_refdef.viewcache.entityvisible[i])
4704 ent = r_refdef.scene.entities[i];
4705 if (!ent->model || !ent->model->DrawSky)
4707 ent->model->DrawSky(ent);
4713 static void R_DrawNoModel(entity_render_t *ent);
4714 static void R_DrawModels(void)
4717 entity_render_t *ent;
4719 for (i = 0;i < r_refdef.scene.numentities;i++)
4721 if (!r_refdef.viewcache.entityvisible[i])
4723 ent = r_refdef.scene.entities[i];
4724 r_refdef.stats.entities++;
4725 if (ent->model && ent->model->Draw != NULL)
4726 ent->model->Draw(ent);
4732 static void R_DrawModelsDepth(void)
4735 entity_render_t *ent;
4737 for (i = 0;i < r_refdef.scene.numentities;i++)
4739 if (!r_refdef.viewcache.entityvisible[i])
4741 ent = r_refdef.scene.entities[i];
4742 if (ent->model && ent->model->DrawDepth != NULL)
4743 ent->model->DrawDepth(ent);
4747 static void R_DrawModelsDebug(void)
4750 entity_render_t *ent;
4752 for (i = 0;i < r_refdef.scene.numentities;i++)
4754 if (!r_refdef.viewcache.entityvisible[i])
4756 ent = r_refdef.scene.entities[i];
4757 if (ent->model && ent->model->DrawDebug != NULL)
4758 ent->model->DrawDebug(ent);
4762 static void R_DrawModelsAddWaterPlanes(void)
4765 entity_render_t *ent;
4767 for (i = 0;i < r_refdef.scene.numentities;i++)
4769 if (!r_refdef.viewcache.entityvisible[i])
4771 ent = r_refdef.scene.entities[i];
4772 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4773 ent->model->DrawAddWaterPlanes(ent);
4777 static void R_View_SetFrustum(void)
4780 double slopex, slopey;
4781 vec3_t forward, left, up, origin;
4783 // we can't trust r_refdef.view.forward and friends in reflected scenes
4784 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4787 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4788 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4789 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4790 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4791 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4792 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4793 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4794 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4795 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4796 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4797 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4798 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4802 zNear = r_refdef.nearclip;
4803 nudge = 1.0 - 1.0 / (1<<23);
4804 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4805 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4806 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4807 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4808 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4809 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4810 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4811 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4817 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4818 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4819 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4820 r_refdef.view.frustum[0].dist = m[15] - m[12];
4822 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4823 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4824 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4825 r_refdef.view.frustum[1].dist = m[15] + m[12];
4827 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4828 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4829 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4830 r_refdef.view.frustum[2].dist = m[15] - m[13];
4832 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4833 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4834 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4835 r_refdef.view.frustum[3].dist = m[15] + m[13];
4837 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4838 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4839 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4840 r_refdef.view.frustum[4].dist = m[15] - m[14];
4842 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4843 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4844 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4845 r_refdef.view.frustum[5].dist = m[15] + m[14];
4848 if (r_refdef.view.useperspective)
4850 slopex = 1.0 / r_refdef.view.frustum_x;
4851 slopey = 1.0 / r_refdef.view.frustum_y;
4852 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
4853 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
4854 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
4855 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
4856 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4858 // Leaving those out was a mistake, those were in the old code, and they
4859 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4860 // I couldn't reproduce it after adding those normalizations. --blub
4861 VectorNormalize(r_refdef.view.frustum[0].normal);
4862 VectorNormalize(r_refdef.view.frustum[1].normal);
4863 VectorNormalize(r_refdef.view.frustum[2].normal);
4864 VectorNormalize(r_refdef.view.frustum[3].normal);
4866 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4867 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]);
4868 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]);
4869 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]);
4870 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]);
4872 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4873 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4874 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4875 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4876 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4880 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
4881 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
4882 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
4883 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
4884 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4885 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
4886 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
4887 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
4888 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
4889 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4891 r_refdef.view.numfrustumplanes = 5;
4893 if (r_refdef.view.useclipplane)
4895 r_refdef.view.numfrustumplanes = 6;
4896 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
4899 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4900 PlaneClassify(r_refdef.view.frustum + i);
4902 // LordHavoc: note to all quake engine coders, Quake had a special case
4903 // for 90 degrees which assumed a square view (wrong), so I removed it,
4904 // Quake2 has it disabled as well.
4906 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
4907 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
4908 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
4909 //PlaneClassify(&frustum[0]);
4911 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
4912 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
4913 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
4914 //PlaneClassify(&frustum[1]);
4916 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
4917 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
4918 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
4919 //PlaneClassify(&frustum[2]);
4921 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
4922 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
4923 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
4924 //PlaneClassify(&frustum[3]);
4927 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
4928 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
4929 //PlaneClassify(&frustum[4]);
4932 void R_View_Update(void)
4934 R_Main_ResizeViewCache();
4935 R_View_SetFrustum();
4936 R_View_WorldVisibility(r_refdef.view.useclipplane);
4937 R_View_UpdateEntityVisible();
4938 R_View_UpdateEntityLighting();
4941 void R_SetupView(qboolean allowwaterclippingplane)
4943 const float *customclipplane = NULL;
4945 if (r_refdef.view.useclipplane && allowwaterclippingplane)
4947 // LordHavoc: couldn't figure out how to make this approach the
4948 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
4949 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
4950 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
4951 dist = r_refdef.view.clipplane.dist;
4952 plane[0] = r_refdef.view.clipplane.normal[0];
4953 plane[1] = r_refdef.view.clipplane.normal[1];
4954 plane[2] = r_refdef.view.clipplane.normal[2];
4956 customclipplane = plane;
4959 if (!r_refdef.view.useperspective)
4960 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);
4961 else if (vid.stencil && r_useinfinitefarclip.integer)
4962 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);
4964 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);
4965 R_SetViewport(&r_refdef.view.viewport);
4968 void R_EntityMatrix(const matrix4x4_t *matrix)
4970 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
4972 gl_modelmatrixchanged = false;
4973 gl_modelmatrix = *matrix;
4974 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
4975 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
4976 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
4977 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
4979 switch(vid.renderpath)
4981 case RENDERPATH_GL20:
4982 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4983 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4985 case RENDERPATH_CGGL:
4987 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix >= 0) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4988 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4991 case RENDERPATH_GL13:
4992 case RENDERPATH_GL11:
4993 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
4999 void R_ResetViewRendering2D(void)
5001 r_viewport_t viewport;
5004 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5005 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);
5006 R_SetViewport(&viewport);
5007 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5008 GL_Color(1, 1, 1, 1);
5009 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5010 GL_BlendFunc(GL_ONE, GL_ZERO);
5011 GL_AlphaTest(false);
5012 GL_ScissorTest(false);
5013 GL_DepthMask(false);
5014 GL_DepthRange(0, 1);
5015 GL_DepthTest(false);
5016 R_EntityMatrix(&identitymatrix);
5017 R_Mesh_ResetTextureState();
5018 GL_PolygonOffset(0, 0);
5019 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5020 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5021 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
5022 qglStencilMask(~0);CHECKGLERROR
5023 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
5024 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
5025 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
5028 void R_ResetViewRendering3D(void)
5033 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5034 GL_Color(1, 1, 1, 1);
5035 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5036 GL_BlendFunc(GL_ONE, GL_ZERO);
5037 GL_AlphaTest(false);
5038 GL_ScissorTest(true);
5040 GL_DepthRange(0, 1);
5042 R_EntityMatrix(&identitymatrix);
5043 R_Mesh_ResetTextureState();
5044 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5045 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5046 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5047 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
5048 qglStencilMask(~0);CHECKGLERROR
5049 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
5050 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
5051 GL_CullFace(r_refdef.view.cullface_back);
5054 void R_RenderScene(void);
5055 void R_RenderWaterPlanes(void);
5057 static void R_Water_StartFrame(void)
5060 int waterwidth, waterheight, texturewidth, textureheight;
5061 r_waterstate_waterplane_t *p;
5063 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5066 switch(vid.renderpath)
5068 case RENDERPATH_GL20:
5069 case RENDERPATH_CGGL:
5071 case RENDERPATH_GL13:
5072 case RENDERPATH_GL11:
5076 // set waterwidth and waterheight to the water resolution that will be
5077 // used (often less than the screen resolution for faster rendering)
5078 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5079 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5081 // calculate desired texture sizes
5082 // can't use water if the card does not support the texture size
5083 if (!r_water.integer || r_showsurfaces.integer)
5084 texturewidth = textureheight = waterwidth = waterheight = 0;
5085 else if (vid.support.arb_texture_non_power_of_two)
5087 texturewidth = waterwidth;
5088 textureheight = waterheight;
5092 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5093 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5096 // allocate textures as needed
5097 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
5099 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5100 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5102 if (p->texture_refraction)
5103 R_FreeTexture(p->texture_refraction);
5104 p->texture_refraction = NULL;
5105 if (p->texture_reflection)
5106 R_FreeTexture(p->texture_reflection);
5107 p->texture_reflection = NULL;
5109 memset(&r_waterstate, 0, sizeof(r_waterstate));
5110 r_waterstate.texturewidth = texturewidth;
5111 r_waterstate.textureheight = textureheight;
5114 if (r_waterstate.texturewidth)
5116 r_waterstate.enabled = true;
5118 // when doing a reduced render (HDR) we want to use a smaller area
5119 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5120 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5122 // set up variables that will be used in shader setup
5123 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5124 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5125 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5126 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5129 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5130 r_waterstate.numwaterplanes = 0;
5133 void R_Water_AddWaterPlane(msurface_t *surface)
5135 int triangleindex, planeindex;
5141 r_waterstate_waterplane_t *p;
5142 texture_t *t = R_GetCurrentTexture(surface->texture);
5143 // just use the first triangle with a valid normal for any decisions
5144 VectorClear(normal);
5145 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5147 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5148 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5149 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5150 TriangleNormal(vert[0], vert[1], vert[2], normal);
5151 if (VectorLength2(normal) >= 0.001)
5155 VectorCopy(normal, plane.normal);
5156 VectorNormalize(plane.normal);
5157 plane.dist = DotProduct(vert[0], plane.normal);
5158 PlaneClassify(&plane);
5159 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5161 // skip backfaces (except if nocullface is set)
5162 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5164 VectorNegate(plane.normal, plane.normal);
5166 PlaneClassify(&plane);
5170 // find a matching plane if there is one
5171 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5172 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5174 if (planeindex >= r_waterstate.maxwaterplanes)
5175 return; // nothing we can do, out of planes
5177 // if this triangle does not fit any known plane rendered this frame, add one
5178 if (planeindex >= r_waterstate.numwaterplanes)
5180 // store the new plane
5181 r_waterstate.numwaterplanes++;
5183 // clear materialflags and pvs
5184 p->materialflags = 0;
5185 p->pvsvalid = false;
5187 // merge this surface's materialflags into the waterplane
5188 p->materialflags |= t->currentmaterialflags;
5189 // merge this surface's PVS into the waterplane
5190 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5191 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5192 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5194 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5199 static void R_Water_ProcessPlanes(void)
5201 r_refdef_view_t originalview;
5202 r_refdef_view_t myview;
5204 r_waterstate_waterplane_t *p;
5206 originalview = r_refdef.view;
5208 // make sure enough textures are allocated
5209 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5211 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5213 if (!p->texture_refraction)
5214 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
5215 if (!p->texture_refraction)
5219 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5221 if (!p->texture_reflection)
5222 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
5223 if (!p->texture_reflection)
5229 r_refdef.view = originalview;
5230 r_refdef.view.showdebug = false;
5231 r_refdef.view.width = r_waterstate.waterwidth;
5232 r_refdef.view.height = r_waterstate.waterheight;
5233 r_refdef.view.useclipplane = true;
5234 myview = r_refdef.view;
5235 r_waterstate.renderingscene = true;
5236 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5238 // render the normal view scene and copy into texture
5239 // (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)
5240 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5242 r_refdef.view = myview;
5243 r_refdef.view.clipplane = p->plane;
5244 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5245 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5246 PlaneClassify(&r_refdef.view.clipplane);
5248 R_ResetViewRendering3D();
5249 R_ClearScreen(r_refdef.fogenabled);
5253 R_Mesh_CopyToTexture(R_GetTexture(p->texture_refraction), 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5256 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5258 r_refdef.view = myview;
5259 // render reflected scene and copy into texture
5260 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5261 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5262 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5263 r_refdef.view.clipplane = p->plane;
5264 // reverse the cullface settings for this render
5265 r_refdef.view.cullface_front = GL_FRONT;
5266 r_refdef.view.cullface_back = GL_BACK;
5267 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5269 r_refdef.view.usecustompvs = true;
5271 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5273 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5276 R_ResetViewRendering3D();
5277 R_ClearScreen(r_refdef.fogenabled);
5281 R_Mesh_CopyToTexture(R_GetTexture(p->texture_reflection), 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5284 r_waterstate.renderingscene = false;
5285 r_refdef.view = originalview;
5286 R_ResetViewRendering3D();
5287 R_ClearScreen(r_refdef.fogenabled);
5291 r_refdef.view = originalview;
5292 r_waterstate.renderingscene = false;
5293 Cvar_SetValueQuick(&r_water, 0);
5294 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5298 void R_Bloom_StartFrame(void)
5300 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5302 switch(vid.renderpath)
5304 case RENDERPATH_GL20:
5305 case RENDERPATH_CGGL:
5307 case RENDERPATH_GL13:
5308 case RENDERPATH_GL11:
5312 // set bloomwidth and bloomheight to the bloom resolution that will be
5313 // used (often less than the screen resolution for faster rendering)
5314 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5315 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5316 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5317 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5318 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5320 // calculate desired texture sizes
5321 if (vid.support.arb_texture_non_power_of_two)
5323 screentexturewidth = r_refdef.view.width;
5324 screentextureheight = r_refdef.view.height;
5325 bloomtexturewidth = r_bloomstate.bloomwidth;
5326 bloomtextureheight = r_bloomstate.bloomheight;
5330 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5331 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5332 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5333 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5336 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))
5338 Cvar_SetValueQuick(&r_hdr, 0);
5339 Cvar_SetValueQuick(&r_bloom, 0);
5340 Cvar_SetValueQuick(&r_motionblur, 0);
5341 Cvar_SetValueQuick(&r_damageblur, 0);
5344 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)))
5345 screentexturewidth = screentextureheight = 0;
5346 if (!r_hdr.integer && !r_bloom.integer)
5347 bloomtexturewidth = bloomtextureheight = 0;
5349 // allocate textures as needed
5350 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5352 if (r_bloomstate.texture_screen)
5353 R_FreeTexture(r_bloomstate.texture_screen);
5354 r_bloomstate.texture_screen = NULL;
5355 r_bloomstate.screentexturewidth = screentexturewidth;
5356 r_bloomstate.screentextureheight = screentextureheight;
5357 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5358 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
5360 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5362 if (r_bloomstate.texture_bloom)
5363 R_FreeTexture(r_bloomstate.texture_bloom);
5364 r_bloomstate.texture_bloom = NULL;
5365 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5366 r_bloomstate.bloomtextureheight = bloomtextureheight;
5367 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5368 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
5371 // when doing a reduced render (HDR) we want to use a smaller area
5372 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5373 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5374 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5375 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5376 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5378 // set up a texcoord array for the full resolution screen image
5379 // (we have to keep this around to copy back during final render)
5380 r_bloomstate.screentexcoord2f[0] = 0;
5381 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5382 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5383 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5384 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5385 r_bloomstate.screentexcoord2f[5] = 0;
5386 r_bloomstate.screentexcoord2f[6] = 0;
5387 r_bloomstate.screentexcoord2f[7] = 0;
5389 // set up a texcoord array for the reduced resolution bloom image
5390 // (which will be additive blended over the screen image)
5391 r_bloomstate.bloomtexcoord2f[0] = 0;
5392 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5393 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5394 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5395 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5396 r_bloomstate.bloomtexcoord2f[5] = 0;
5397 r_bloomstate.bloomtexcoord2f[6] = 0;
5398 r_bloomstate.bloomtexcoord2f[7] = 0;
5400 if (r_hdr.integer || r_bloom.integer)
5402 r_bloomstate.enabled = true;
5403 r_bloomstate.hdr = r_hdr.integer != 0;
5406 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);
5409 void R_Bloom_CopyBloomTexture(float colorscale)
5411 r_refdef.stats.bloom++;
5413 // scale down screen texture to the bloom texture size
5415 R_SetViewport(&r_bloomstate.viewport);
5416 GL_BlendFunc(GL_ONE, GL_ZERO);
5417 GL_Color(colorscale, colorscale, colorscale, 1);
5418 // TODO: optimize with multitexture or GLSL
5419 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5420 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5421 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5422 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5424 // we now have a bloom image in the framebuffer
5425 // copy it into the bloom image texture for later processing
5426 R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5427 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5430 void R_Bloom_CopyHDRTexture(void)
5432 R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5433 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5436 void R_Bloom_MakeTexture(void)
5439 float xoffset, yoffset, r, brighten;
5441 r_refdef.stats.bloom++;
5443 R_ResetViewRendering2D();
5444 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5445 R_Mesh_ColorPointer(NULL, 0, 0);
5447 // we have a bloom image in the framebuffer
5449 R_SetViewport(&r_bloomstate.viewport);
5451 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5454 r = bound(0, r_bloom_colorexponent.value / x, 1);
5455 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5456 GL_Color(r, r, r, 1);
5457 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5458 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5459 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5460 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5462 // copy the vertically blurred bloom view to a texture
5463 GL_ActiveTexture(0);
5465 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
5466 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5469 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5470 brighten = r_bloom_brighten.value;
5472 brighten *= r_hdr_range.value;
5473 brighten = sqrt(brighten);
5475 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5476 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5477 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
5479 for (dir = 0;dir < 2;dir++)
5481 // blend on at multiple vertical offsets to achieve a vertical blur
5482 // TODO: do offset blends using GLSL
5483 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5484 GL_BlendFunc(GL_ONE, GL_ZERO);
5485 for (x = -range;x <= range;x++)
5487 if (!dir){xoffset = 0;yoffset = x;}
5488 else {xoffset = x;yoffset = 0;}
5489 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5490 yoffset /= (float)r_bloomstate.bloomtextureheight;
5491 // compute a texcoord array with the specified x and y offset
5492 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5493 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5494 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5495 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5496 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5497 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5498 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5499 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5500 // this r value looks like a 'dot' particle, fading sharply to
5501 // black at the edges
5502 // (probably not realistic but looks good enough)
5503 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5504 //r = brighten/(range*2+1);
5505 r = brighten / (range * 2 + 1);
5507 r *= (1 - x*x/(float)(range*range));
5508 GL_Color(r, r, r, 1);
5509 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5510 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5511 GL_BlendFunc(GL_ONE, GL_ONE);
5514 // copy the vertically blurred bloom view to a texture
5515 GL_ActiveTexture(0);
5517 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
5518 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5521 // apply subtract last
5522 // (just like it would be in a GLSL shader)
5523 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
5525 GL_BlendFunc(GL_ONE, GL_ZERO);
5526 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5527 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5528 GL_Color(1, 1, 1, 1);
5529 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5530 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5532 GL_BlendFunc(GL_ONE, GL_ONE);
5533 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
5534 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5535 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5536 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
5537 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5538 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5539 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
5541 // copy the darkened bloom view to a texture
5542 R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_bloom), 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5543 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5547 void R_HDR_RenderBloomTexture(void)
5549 int oldwidth, oldheight;
5550 float oldcolorscale;
5552 oldcolorscale = r_refdef.view.colorscale;
5553 oldwidth = r_refdef.view.width;
5554 oldheight = r_refdef.view.height;
5555 r_refdef.view.width = r_bloomstate.bloomwidth;
5556 r_refdef.view.height = r_bloomstate.bloomheight;
5558 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5559 // TODO: add exposure compensation features
5560 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5562 r_refdef.view.showdebug = false;
5563 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5565 R_ResetViewRendering3D();
5567 R_ClearScreen(r_refdef.fogenabled);
5568 if (r_timereport_active)
5569 R_TimeReport("HDRclear");
5572 if (r_timereport_active)
5573 R_TimeReport("visibility");
5575 // only do secondary renders with HDR if r_hdr is 2 or higher
5576 r_waterstate.numwaterplanes = 0;
5577 if (r_waterstate.enabled && r_hdr.integer >= 2)
5578 R_RenderWaterPlanes();
5580 r_refdef.view.showdebug = true;
5582 r_waterstate.numwaterplanes = 0;
5584 R_ResetViewRendering2D();
5586 R_Bloom_CopyHDRTexture();
5587 R_Bloom_MakeTexture();
5589 // restore the view settings
5590 r_refdef.view.width = oldwidth;
5591 r_refdef.view.height = oldheight;
5592 r_refdef.view.colorscale = oldcolorscale;
5593 r_frame++; // used only by R_GetCurrentTexture
5595 R_ResetViewRendering3D();
5597 R_ClearScreen(r_refdef.fogenabled);
5598 if (r_timereport_active)
5599 R_TimeReport("viewclear");
5602 static void R_BlendView(void)
5604 unsigned int permutation;
5605 float uservecs[4][4];
5607 switch (vid.renderpath)
5609 case RENDERPATH_GL20:
5610 case RENDERPATH_CGGL:
5612 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5613 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5614 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5615 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5616 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5618 if (r_bloomstate.texture_screen)
5620 // make sure the buffer is available
5621 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5623 R_ResetViewRendering2D();
5624 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5625 R_Mesh_ColorPointer(NULL, 0, 0);
5627 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5629 // declare variables
5631 static float avgspeed;
5633 speed = VectorLength(cl.movement_velocity);
5635 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5636 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5638 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5639 speed = bound(0, speed, 1);
5640 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5642 // calculate values into a standard alpha
5643 cl.motionbluralpha = 1 - exp(-
5645 (r_motionblur.value * speed / 80)
5647 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5650 max(0.0001, cl.time - cl.oldtime) // fps independent
5653 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5654 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5656 if (cl.motionbluralpha > 0)
5658 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5659 GL_Color(1, 1, 1, cl.motionbluralpha);
5660 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5661 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5662 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5663 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5667 // copy view into the screen texture
5668 R_Mesh_CopyToTexture(R_GetTexture(r_bloomstate.texture_screen), 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5669 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5671 else if (!r_bloomstate.texture_bloom)
5673 // we may still have to do view tint...
5674 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
5676 // apply a color tint to the whole view
5677 R_ResetViewRendering2D();
5678 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5679 R_Mesh_ColorPointer(NULL, 0, 0);
5680 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5681 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5682 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5683 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5685 break; // no screen processing, no bloom, skip it
5688 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
5690 // render simple bloom effect
5691 // copy the screen and shrink it and darken it for the bloom process
5692 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
5693 // make the bloom texture
5694 R_Bloom_MakeTexture();
5697 #if _MSC_VER >= 1400
5698 #define sscanf sscanf_s
5700 memset(uservecs, 0, sizeof(uservecs));
5701 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
5702 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
5703 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
5704 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
5706 R_ResetViewRendering2D();
5707 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5708 R_Mesh_ColorPointer(NULL, 0, 0);
5709 GL_Color(1, 1, 1, 1);
5710 GL_BlendFunc(GL_ONE, GL_ZERO);
5711 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
5712 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
5714 switch(vid.renderpath)
5716 case RENDERPATH_GL20:
5717 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
5718 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , R_GetTexture(r_bloomstate.texture_screen));
5719 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , R_GetTexture(r_bloomstate.texture_bloom ));
5720 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps ));
5721 if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5722 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime , cl.time);
5723 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
5724 if (r_glsl_permutation->loc_UserVec1 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
5725 if (r_glsl_permutation->loc_UserVec2 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
5726 if (r_glsl_permutation->loc_UserVec3 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
5727 if (r_glsl_permutation->loc_UserVec4 >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
5728 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
5730 case RENDERPATH_CGGL:
5732 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
5733 if (r_cg_permutation->fp_Texture_First ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_First , R_GetTexture(r_bloomstate.texture_screen));
5734 if (r_cg_permutation->fp_Texture_Second ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Second , R_GetTexture(r_bloomstate.texture_bloom ));
5735 if (r_cg_permutation->fp_Texture_GammaRamps) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_GammaRamps, R_GetTexture(r_texture_gammaramps ));
5736 if (r_cg_permutation->fp_ViewTintColor ) cgGLSetParameter4f( r_cg_permutation->fp_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5737 if (r_cg_permutation->fp_ClientTime ) cgGLSetParameter1f( r_cg_permutation->fp_ClientTime , cl.time);
5738 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
5739 if (r_cg_permutation->fp_UserVec1 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
5740 if (r_cg_permutation->fp_UserVec2 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
5741 if (r_cg_permutation->fp_UserVec3 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
5742 if (r_cg_permutation->fp_UserVec4 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
5743 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);
5749 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5750 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5752 case RENDERPATH_GL13:
5753 case RENDERPATH_GL11:
5754 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
5756 // apply a color tint to the whole view
5757 R_ResetViewRendering2D();
5758 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
5759 R_Mesh_ColorPointer(NULL, 0, 0);
5760 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
5761 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5762 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
5763 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
5769 matrix4x4_t r_waterscrollmatrix;
5771 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
5773 if (r_refdef.fog_density)
5775 r_refdef.fogcolor[0] = r_refdef.fog_red;
5776 r_refdef.fogcolor[1] = r_refdef.fog_green;
5777 r_refdef.fogcolor[2] = r_refdef.fog_blue;
5779 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
5780 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
5781 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
5782 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
5786 VectorCopy(r_refdef.fogcolor, fogvec);
5787 // color.rgb *= ContrastBoost * SceneBrightness;
5788 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
5789 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
5790 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
5791 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
5796 void R_UpdateVariables(void)
5800 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
5802 r_refdef.farclip = r_farclip_base.value;
5803 if (r_refdef.scene.worldmodel)
5804 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
5805 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
5807 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
5808 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
5809 r_refdef.polygonfactor = 0;
5810 r_refdef.polygonoffset = 0;
5811 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5812 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
5814 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
5815 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
5816 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
5817 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
5818 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
5819 if (r_showsurfaces.integer)
5821 r_refdef.scene.rtworld = false;
5822 r_refdef.scene.rtworldshadows = false;
5823 r_refdef.scene.rtdlight = false;
5824 r_refdef.scene.rtdlightshadows = false;
5825 r_refdef.lightmapintensity = 0;
5828 if (gamemode == GAME_NEHAHRA)
5830 if (gl_fogenable.integer)
5832 r_refdef.oldgl_fogenable = true;
5833 r_refdef.fog_density = gl_fogdensity.value;
5834 r_refdef.fog_red = gl_fogred.value;
5835 r_refdef.fog_green = gl_foggreen.value;
5836 r_refdef.fog_blue = gl_fogblue.value;
5837 r_refdef.fog_alpha = 1;
5838 r_refdef.fog_start = 0;
5839 r_refdef.fog_end = gl_skyclip.value;
5840 r_refdef.fog_height = 1<<30;
5841 r_refdef.fog_fadedepth = 128;
5843 else if (r_refdef.oldgl_fogenable)
5845 r_refdef.oldgl_fogenable = false;
5846 r_refdef.fog_density = 0;
5847 r_refdef.fog_red = 0;
5848 r_refdef.fog_green = 0;
5849 r_refdef.fog_blue = 0;
5850 r_refdef.fog_alpha = 0;
5851 r_refdef.fog_start = 0;
5852 r_refdef.fog_end = 0;
5853 r_refdef.fog_height = 1<<30;
5854 r_refdef.fog_fadedepth = 128;
5858 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
5859 r_refdef.fog_start = max(0, r_refdef.fog_start);
5860 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
5862 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
5864 if (r_refdef.fog_density && r_drawfog.integer)
5866 r_refdef.fogenabled = true;
5867 // this is the point where the fog reaches 0.9986 alpha, which we
5868 // consider a good enough cutoff point for the texture
5869 // (0.9986 * 256 == 255.6)
5870 if (r_fog_exp2.integer)
5871 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
5873 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
5874 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
5875 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
5876 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
5877 // fog color was already set
5878 // update the fog texture
5879 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)
5880 R_BuildFogTexture();
5883 r_refdef.fogenabled = false;
5885 switch(vid.renderpath)
5887 case RENDERPATH_GL20:
5888 case RENDERPATH_CGGL:
5889 if(v_glslgamma.integer && !vid_gammatables_trivial)
5891 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
5893 // build GLSL gamma texture
5894 #define RAMPWIDTH 256
5895 unsigned short ramp[RAMPWIDTH * 3];
5896 unsigned char rampbgr[RAMPWIDTH][4];
5899 r_texture_gammaramps_serial = vid_gammatables_serial;
5901 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
5902 for(i = 0; i < RAMPWIDTH; ++i)
5904 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5905 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
5906 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
5909 if (r_texture_gammaramps)
5911 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
5915 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
5921 // remove GLSL gamma texture
5924 case RENDERPATH_GL13:
5925 case RENDERPATH_GL11:
5930 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
5931 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
5937 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
5938 if( scenetype != r_currentscenetype ) {
5939 // store the old scenetype
5940 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
5941 r_currentscenetype = scenetype;
5942 // move in the new scene
5943 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
5952 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
5954 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
5955 if( scenetype == r_currentscenetype ) {
5956 return &r_refdef.scene;
5958 return &r_scenes_store[ scenetype ];
5967 void R_RenderView(void)
5969 if (r_timereport_active)
5970 R_TimeReport("start");
5971 r_frame++; // used only by R_GetCurrentTexture
5972 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
5974 if (!r_drawentities.integer)
5975 r_refdef.scene.numentities = 0;
5977 R_AnimCache_ClearCache();
5978 R_FrameData_NewFrame();
5980 if (r_refdef.view.isoverlay)
5982 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
5983 GL_Clear( GL_DEPTH_BUFFER_BIT );
5984 R_TimeReport("depthclear");
5986 r_refdef.view.showdebug = false;
5988 r_waterstate.enabled = false;
5989 r_waterstate.numwaterplanes = 0;
5997 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
5998 return; //Host_Error ("R_RenderView: NULL worldmodel");
6000 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
6002 // break apart the view matrix into vectors for various purposes
6003 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
6004 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
6005 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
6006 VectorNegate(r_refdef.view.left, r_refdef.view.right);
6007 // make an inverted copy of the view matrix for tracking sprites
6008 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
6010 R_Shadow_UpdateWorldLightSelection();
6012 R_Bloom_StartFrame();
6013 R_Water_StartFrame();
6016 if (r_timereport_active)
6017 R_TimeReport("viewsetup");
6019 R_ResetViewRendering3D();
6021 if (r_refdef.view.clear || r_refdef.fogenabled)
6023 R_ClearScreen(r_refdef.fogenabled);
6024 if (r_timereport_active)
6025 R_TimeReport("viewclear");
6027 r_refdef.view.clear = true;
6029 // this produces a bloom texture to be used in R_BlendView() later
6030 if (r_hdr.integer && r_bloomstate.bloomwidth)
6031 R_HDR_RenderBloomTexture();
6033 r_refdef.view.showdebug = true;
6036 if (r_timereport_active)
6037 R_TimeReport("visibility");
6039 r_waterstate.numwaterplanes = 0;
6040 if (r_waterstate.enabled)
6041 R_RenderWaterPlanes();
6044 r_waterstate.numwaterplanes = 0;
6047 if (r_timereport_active)
6048 R_TimeReport("blendview");
6050 GL_Scissor(0, 0, vid.width, vid.height);
6051 GL_ScissorTest(false);
6055 void R_RenderWaterPlanes(void)
6057 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6059 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6060 if (r_timereport_active)
6061 R_TimeReport("waterworld");
6064 // don't let sound skip if going slow
6065 if (r_refdef.scene.extraupdate)
6068 R_DrawModelsAddWaterPlanes();
6069 if (r_timereport_active)
6070 R_TimeReport("watermodels");
6072 if (r_waterstate.numwaterplanes)
6074 R_Water_ProcessPlanes();
6075 if (r_timereport_active)
6076 R_TimeReport("waterscenes");
6080 extern void R_DrawLightningBeams (void);
6081 extern void VM_CL_AddPolygonsToMeshQueue (void);
6082 extern void R_DrawPortals (void);
6083 extern cvar_t cl_locs_show;
6084 static void R_DrawLocs(void);
6085 static void R_DrawEntityBBoxes(void);
6086 static void R_DrawModelDecals(void);
6087 extern cvar_t cl_decals_newsystem;
6088 extern qboolean r_shadow_usingdeferredprepass;
6089 void R_RenderScene(void)
6091 r_refdef.stats.renders++;
6095 // don't let sound skip if going slow
6096 if (r_refdef.scene.extraupdate)
6099 R_MeshQueue_BeginScene();
6103 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);
6105 if (cl.csqc_vidvars.drawworld)
6107 // don't let sound skip if going slow
6108 if (r_refdef.scene.extraupdate)
6111 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6113 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6114 if (r_timereport_active)
6115 R_TimeReport("worldsky");
6118 if (R_DrawBrushModelsSky() && r_timereport_active)
6119 R_TimeReport("bmodelsky");
6121 if (skyrendermasked && skyrenderlater)
6123 // we have to force off the water clipping plane while rendering sky
6127 if (r_timereport_active)
6128 R_TimeReport("sky");
6132 R_AnimCache_CacheVisibleEntities();
6133 if (r_timereport_active)
6134 R_TimeReport("animation");
6136 R_Shadow_PrepareLights();
6137 if (r_timereport_active)
6138 R_TimeReport("preparelights");
6140 if (r_shadow_usingdeferredprepass)
6141 R_Shadow_DrawPrepass();
6143 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6145 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6146 if (r_timereport_active)
6147 R_TimeReport("worlddepth");
6149 if (r_depthfirst.integer >= 2)
6151 R_DrawModelsDepth();
6152 if (r_timereport_active)
6153 R_TimeReport("modeldepth");
6156 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6158 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6159 if (r_timereport_active)
6160 R_TimeReport("world");
6163 // don't let sound skip if going slow
6164 if (r_refdef.scene.extraupdate)
6168 if (r_timereport_active)
6169 R_TimeReport("models");
6171 // don't let sound skip if going slow
6172 if (r_refdef.scene.extraupdate)
6175 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6177 R_DrawModelShadows();
6178 R_ResetViewRendering3D();
6179 // don't let sound skip if going slow
6180 if (r_refdef.scene.extraupdate)
6184 if (!r_shadow_usingdeferredprepass)
6186 R_Shadow_DrawLights();
6187 if (r_timereport_active)
6188 R_TimeReport("rtlights");
6191 // don't let sound skip if going slow
6192 if (r_refdef.scene.extraupdate)
6195 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6197 R_DrawModelShadows();
6198 R_ResetViewRendering3D();
6199 // don't let sound skip if going slow
6200 if (r_refdef.scene.extraupdate)
6204 if (cl.csqc_vidvars.drawworld)
6206 if (cl_decals_newsystem.integer)
6208 R_DrawModelDecals();
6209 if (r_timereport_active)
6210 R_TimeReport("modeldecals");
6215 if (r_timereport_active)
6216 R_TimeReport("decals");
6220 if (r_timereport_active)
6221 R_TimeReport("particles");
6224 if (r_timereport_active)
6225 R_TimeReport("explosions");
6227 R_DrawLightningBeams();
6228 if (r_timereport_active)
6229 R_TimeReport("lightning");
6232 VM_CL_AddPolygonsToMeshQueue();
6234 if (r_refdef.view.showdebug)
6236 if (cl_locs_show.integer)
6239 if (r_timereport_active)
6240 R_TimeReport("showlocs");
6243 if (r_drawportals.integer)
6246 if (r_timereport_active)
6247 R_TimeReport("portals");
6250 if (r_showbboxes.value > 0)
6252 R_DrawEntityBBoxes();
6253 if (r_timereport_active)
6254 R_TimeReport("bboxes");
6258 R_MeshQueue_RenderTransparent();
6259 if (r_timereport_active)
6260 R_TimeReport("drawtrans");
6262 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))
6264 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6265 if (r_timereport_active)
6266 R_TimeReport("worlddebug");
6267 R_DrawModelsDebug();
6268 if (r_timereport_active)
6269 R_TimeReport("modeldebug");
6272 if (cl.csqc_vidvars.drawworld)
6274 R_Shadow_DrawCoronas();
6275 if (r_timereport_active)
6276 R_TimeReport("coronas");
6279 // don't let sound skip if going slow
6280 if (r_refdef.scene.extraupdate)
6283 R_ResetViewRendering2D();
6286 static const unsigned short bboxelements[36] =
6296 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6299 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6301 RSurf_ActiveWorldEntity();
6303 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6304 GL_DepthMask(false);
6305 GL_DepthRange(0, 1);
6306 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6307 R_Mesh_ResetTextureState();
6309 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6310 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6311 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6312 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6313 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6314 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6315 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6316 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6317 R_FillColors(color4f, 8, cr, cg, cb, ca);
6318 if (r_refdef.fogenabled)
6320 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6322 f1 = RSurf_FogVertex(v);
6324 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6325 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6326 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6329 R_Mesh_VertexPointer(vertex3f, 0, 0);
6330 R_Mesh_ColorPointer(color4f, 0, 0);
6331 R_Mesh_ResetTextureState();
6332 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6333 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
6336 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6340 prvm_edict_t *edict;
6341 prvm_prog_t *prog_save = prog;
6343 // this function draws bounding boxes of server entities
6347 GL_CullFace(GL_NONE);
6348 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6352 for (i = 0;i < numsurfaces;i++)
6354 edict = PRVM_EDICT_NUM(surfacelist[i]);
6355 switch ((int)edict->fields.server->solid)
6357 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6358 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6359 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6360 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6361 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6362 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6364 color[3] *= r_showbboxes.value;
6365 color[3] = bound(0, color[3], 1);
6366 GL_DepthTest(!r_showdisabledepthtest.integer);
6367 GL_CullFace(r_refdef.view.cullface_front);
6368 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6374 static void R_DrawEntityBBoxes(void)
6377 prvm_edict_t *edict;
6379 prvm_prog_t *prog_save = prog;
6381 // this function draws bounding boxes of server entities
6387 for (i = 0;i < prog->num_edicts;i++)
6389 edict = PRVM_EDICT_NUM(i);
6390 if (edict->priv.server->free)
6392 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6393 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6395 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6397 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6398 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6404 static const int nomodelelement3i[24] =
6416 static const unsigned short nomodelelement3s[24] =
6428 static const float nomodelvertex3f[6*3] =
6438 static const float nomodelcolor4f[6*4] =
6440 0.0f, 0.0f, 0.5f, 1.0f,
6441 0.0f, 0.0f, 0.5f, 1.0f,
6442 0.0f, 0.5f, 0.0f, 1.0f,
6443 0.0f, 0.5f, 0.0f, 1.0f,
6444 0.5f, 0.0f, 0.0f, 1.0f,
6445 0.5f, 0.0f, 0.0f, 1.0f
6448 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6454 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);
6456 // this is only called once per entity so numsurfaces is always 1, and
6457 // surfacelist is always {0}, so this code does not handle batches
6459 if (rsurface.ent_flags & RENDER_ADDITIVE)
6461 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6462 GL_DepthMask(false);
6464 else if (rsurface.colormod[3] < 1)
6466 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6467 GL_DepthMask(false);
6471 GL_BlendFunc(GL_ONE, GL_ZERO);
6474 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6475 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6476 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6477 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6478 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6479 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6480 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6481 R_Mesh_ColorPointer(color4f, 0, 0);
6482 for (i = 0, c = color4f;i < 6;i++, c += 4)
6484 c[0] *= rsurface.colormod[0];
6485 c[1] *= rsurface.colormod[1];
6486 c[2] *= rsurface.colormod[2];
6487 c[3] *= rsurface.colormod[3];
6489 if (r_refdef.fogenabled)
6491 for (i = 0, c = color4f;i < 6;i++, c += 4)
6493 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
6495 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6496 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6497 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6500 R_Mesh_ResetTextureState();
6501 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
6504 void R_DrawNoModel(entity_render_t *ent)
6507 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6508 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6509 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6511 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6514 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6516 vec3_t right1, right2, diff, normal;
6518 VectorSubtract (org2, org1, normal);
6520 // calculate 'right' vector for start
6521 VectorSubtract (r_refdef.view.origin, org1, diff);
6522 CrossProduct (normal, diff, right1);
6523 VectorNormalize (right1);
6525 // calculate 'right' vector for end
6526 VectorSubtract (r_refdef.view.origin, org2, diff);
6527 CrossProduct (normal, diff, right2);
6528 VectorNormalize (right2);
6530 vert[ 0] = org1[0] + width * right1[0];
6531 vert[ 1] = org1[1] + width * right1[1];
6532 vert[ 2] = org1[2] + width * right1[2];
6533 vert[ 3] = org1[0] - width * right1[0];
6534 vert[ 4] = org1[1] - width * right1[1];
6535 vert[ 5] = org1[2] - width * right1[2];
6536 vert[ 6] = org2[0] - width * right2[0];
6537 vert[ 7] = org2[1] - width * right2[1];
6538 vert[ 8] = org2[2] - width * right2[2];
6539 vert[ 9] = org2[0] + width * right2[0];
6540 vert[10] = org2[1] + width * right2[1];
6541 vert[11] = org2[2] + width * right2[2];
6544 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)
6546 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6547 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6548 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6549 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6550 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6551 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6552 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6553 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6554 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6555 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6556 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6557 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
6560 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
6565 VectorSet(v, x, y, z);
6566 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
6567 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
6569 if (i == mesh->numvertices)
6571 if (mesh->numvertices < mesh->maxvertices)
6573 VectorCopy(v, vertex3f);
6574 mesh->numvertices++;
6576 return mesh->numvertices;
6582 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
6586 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6587 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
6588 e = mesh->element3i + mesh->numtriangles * 3;
6589 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
6591 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
6592 if (mesh->numtriangles < mesh->maxtriangles)
6597 mesh->numtriangles++;
6599 element[1] = element[2];
6603 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
6607 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6608 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
6609 e = mesh->element3i + mesh->numtriangles * 3;
6610 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
6612 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
6613 if (mesh->numtriangles < mesh->maxtriangles)
6618 mesh->numtriangles++;
6620 element[1] = element[2];
6624 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
6625 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
6627 int planenum, planenum2;
6630 mplane_t *plane, *plane2;
6632 double temppoints[2][256*3];
6633 // figure out how large a bounding box we need to properly compute this brush
6635 for (w = 0;w < numplanes;w++)
6636 maxdist = max(maxdist, fabs(planes[w].dist));
6637 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
6638 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
6639 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
6643 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
6644 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
6646 if (planenum2 == planenum)
6648 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);
6651 if (tempnumpoints < 3)
6653 // generate elements forming a triangle fan for this polygon
6654 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
6658 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)
6660 texturelayer_t *layer;
6661 layer = t->currentlayers + t->currentnumlayers++;
6663 layer->depthmask = depthmask;
6664 layer->blendfunc1 = blendfunc1;
6665 layer->blendfunc2 = blendfunc2;
6666 layer->texture = texture;
6667 layer->texmatrix = *matrix;
6668 layer->color[0] = r;
6669 layer->color[1] = g;
6670 layer->color[2] = b;
6671 layer->color[3] = a;
6674 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
6677 index = parms[2] + r_refdef.scene.time * parms[3];
6678 index -= floor(index);
6682 case Q3WAVEFUNC_NONE:
6683 case Q3WAVEFUNC_NOISE:
6684 case Q3WAVEFUNC_COUNT:
6687 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
6688 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
6689 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
6690 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
6691 case Q3WAVEFUNC_TRIANGLE:
6693 f = index - floor(index);
6704 return (float)(parms[0] + parms[1] * f);
6707 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
6712 matrix4x4_t matrix, temp;
6713 switch(tcmod->tcmod)
6717 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6718 matrix = r_waterscrollmatrix;
6720 matrix = identitymatrix;
6722 case Q3TCMOD_ENTITYTRANSLATE:
6723 // this is used in Q3 to allow the gamecode to control texcoord
6724 // scrolling on the entity, which is not supported in darkplaces yet.
6725 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
6727 case Q3TCMOD_ROTATE:
6728 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
6729 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
6730 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
6733 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
6735 case Q3TCMOD_SCROLL:
6736 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
6738 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
6739 w = (int) tcmod->parms[0];
6740 h = (int) tcmod->parms[1];
6741 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
6743 idx = (int) floor(f * w * h);
6744 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
6746 case Q3TCMOD_STRETCH:
6747 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
6748 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
6750 case Q3TCMOD_TRANSFORM:
6751 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
6752 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
6753 VectorSet(tcmat + 6, 0 , 0 , 1);
6754 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
6755 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
6757 case Q3TCMOD_TURBULENT:
6758 // this is handled in the RSurf_PrepareVertices function
6759 matrix = identitymatrix;
6763 Matrix4x4_Concat(texmatrix, &matrix, &temp);
6766 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
6768 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
6769 char name[MAX_QPATH];
6770 skinframe_t *skinframe;
6771 unsigned char pixels[296*194];
6772 strlcpy(cache->name, skinname, sizeof(cache->name));
6773 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
6774 if (developer_loading.integer)
6775 Con_Printf("loading %s\n", name);
6776 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6777 if (!skinframe || !skinframe->base)
6780 fs_offset_t filesize;
6782 f = FS_LoadFile(name, tempmempool, true, &filesize);
6785 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
6786 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
6790 cache->skinframe = skinframe;
6793 texture_t *R_GetCurrentTexture(texture_t *t)
6796 const entity_render_t *ent = rsurface.entity;
6797 dp_model_t *model = ent->model;
6798 q3shaderinfo_layer_tcmod_t *tcmod;
6800 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
6801 return t->currentframe;
6802 t->update_lastrenderframe = r_frame;
6803 t->update_lastrenderentity = (void *)ent;
6805 // switch to an alternate material if this is a q1bsp animated material
6807 texture_t *texture = t;
6808 int s = rsurface.ent_skinnum;
6809 if ((unsigned int)s >= (unsigned int)model->numskins)
6811 if (model->skinscenes)
6813 if (model->skinscenes[s].framecount > 1)
6814 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
6816 s = model->skinscenes[s].firstframe;
6819 t = t + s * model->num_surfaces;
6822 // use an alternate animation if the entity's frame is not 0,
6823 // and only if the texture has an alternate animation
6824 if (rsurface.ent_alttextures && t->anim_total[1])
6825 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
6827 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
6829 texture->currentframe = t;
6832 // update currentskinframe to be a qw skin or animation frame
6833 if (rsurface.ent_qwskin >= 0)
6835 i = rsurface.ent_qwskin;
6836 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
6838 r_qwskincache_size = cl.maxclients;
6840 Mem_Free(r_qwskincache);
6841 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
6843 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
6844 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
6845 t->currentskinframe = r_qwskincache[i].skinframe;
6846 if (t->currentskinframe == NULL)
6847 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6849 else if (t->numskinframes >= 2)
6850 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
6851 if (t->backgroundnumskinframes >= 2)
6852 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
6854 t->currentmaterialflags = t->basematerialflags;
6855 t->currentalpha = rsurface.colormod[3];
6856 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
6857 t->currentalpha *= r_wateralpha.value;
6858 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
6859 t->currentalpha *= t->r_water_wateralpha;
6860 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
6861 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
6862 if (!(rsurface.ent_flags & RENDER_LIGHT))
6863 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
6864 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6866 // pick a model lighting mode
6867 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
6868 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
6870 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
6872 if (rsurface.ent_flags & RENDER_ADDITIVE)
6873 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6874 else if (t->currentalpha < 1)
6875 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
6876 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
6877 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
6878 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
6879 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
6880 if (t->backgroundnumskinframes)
6881 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
6882 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
6884 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
6885 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
6888 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
6889 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
6890 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
6892 // there is no tcmod
6893 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
6895 t->currenttexmatrix = r_waterscrollmatrix;
6896 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
6898 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
6900 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
6901 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
6904 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6905 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
6906 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
6907 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
6909 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
6910 if (t->currentskinframe->qpixels)
6911 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
6912 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
6913 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
6914 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
6915 t->nmaptexture = t->currentskinframe->nmap;
6916 t->glosstexture = r_texture_black;
6917 t->glowtexture = t->currentskinframe->glow;
6918 t->fogtexture = t->currentskinframe->fog;
6919 if (t->backgroundnumskinframes)
6921 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
6922 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
6923 t->backgroundglosstexture = r_texture_black;
6924 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
6928 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
6929 t->backgroundnmaptexture = r_texture_blanknormalmap;
6930 t->backgroundglosstexture = r_texture_black;
6931 t->backgroundglowtexture = NULL;
6933 t->specularpower = r_shadow_glossexponent.value;
6934 // TODO: store reference values for these in the texture?
6935 t->specularscale = 0;
6936 if (r_shadow_gloss.integer > 0)
6938 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
6940 if (r_shadow_glossintensity.value > 0)
6942 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
6943 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
6944 t->specularscale = r_shadow_glossintensity.value;
6947 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
6949 t->glosstexture = r_texture_white;
6950 t->backgroundglosstexture = r_texture_white;
6951 t->specularscale = r_shadow_gloss2intensity.value;
6952 t->specularpower = r_shadow_gloss2exponent.value;
6955 t->specularscale *= t->specularscalemod;
6956 t->specularpower *= t->specularpowermod;
6958 // lightmaps mode looks bad with dlights using actual texturing, so turn
6959 // off the colormap and glossmap, but leave the normalmap on as it still
6960 // accurately represents the shading involved
6961 if (gl_lightmaps.integer)
6963 t->basetexture = r_texture_grey128;
6964 t->pantstexture = r_texture_black;
6965 t->shirttexture = r_texture_black;
6966 t->nmaptexture = r_texture_blanknormalmap;
6967 t->glosstexture = r_texture_black;
6968 t->glowtexture = NULL;
6969 t->fogtexture = NULL;
6970 t->backgroundbasetexture = NULL;
6971 t->backgroundnmaptexture = r_texture_blanknormalmap;
6972 t->backgroundglosstexture = r_texture_black;
6973 t->backgroundglowtexture = NULL;
6974 t->specularscale = 0;
6975 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
6978 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
6979 VectorClear(t->dlightcolor);
6980 t->currentnumlayers = 0;
6981 if (t->currentmaterialflags & MATERIALFLAG_WALL)
6983 int blendfunc1, blendfunc2;
6985 if (t->currentmaterialflags & MATERIALFLAG_ADD)
6987 blendfunc1 = GL_SRC_ALPHA;
6988 blendfunc2 = GL_ONE;
6990 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
6992 blendfunc1 = GL_SRC_ALPHA;
6993 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
6995 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
6997 blendfunc1 = t->customblendfunc[0];
6998 blendfunc2 = t->customblendfunc[1];
7002 blendfunc1 = GL_ONE;
7003 blendfunc2 = GL_ZERO;
7005 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7006 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7008 // fullbright is not affected by r_refdef.lightmapintensity
7009 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]);
7010 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7011 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &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]);
7012 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7013 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &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]);
7017 vec3_t ambientcolor;
7019 // set the color tint used for lights affecting this surface
7020 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7022 // q3bsp has no lightmap updates, so the lightstylevalue that
7023 // would normally be baked into the lightmap must be
7024 // applied to the color
7025 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7026 if (model->type == mod_brushq3)
7027 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7028 colorscale *= r_refdef.lightmapintensity;
7029 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7030 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7031 // basic lit geometry
7032 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]);
7033 // add pants/shirt if needed
7034 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7035 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &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]);
7036 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7037 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &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]);
7038 // now add ambient passes if needed
7039 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7041 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]);
7042 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7043 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
7044 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7045 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
7048 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7049 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
7050 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7052 // if this is opaque use alpha blend which will darken the earlier
7055 // if this is an alpha blended material, all the earlier passes
7056 // were darkened by fog already, so we only need to add the fog
7057 // color ontop through the fog mask texture
7059 // if this is an additive blended material, all the earlier passes
7060 // were darkened by fog already, and we should not add fog color
7061 // (because the background was not darkened, there is no fog color
7062 // that was lost behind it).
7063 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
7067 return t->currentframe;
7070 rsurfacestate_t rsurface;
7072 void R_Mesh_ResizeArrays(int newvertices)
7075 if (rsurface.array_size >= newvertices)
7077 if (rsurface.array_modelvertex3f)
7078 Mem_Free(rsurface.array_modelvertex3f);
7079 rsurface.array_size = (newvertices + 1023) & ~1023;
7080 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
7081 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
7082 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
7083 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
7084 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
7085 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
7086 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
7087 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
7088 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
7089 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
7090 rsurface.array_color4f = base + rsurface.array_size * 27;
7091 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
7094 void RSurf_ActiveWorldEntity(void)
7096 dp_model_t *model = r_refdef.scene.worldmodel;
7097 //if (rsurface.entity == r_refdef.scene.worldentity)
7099 rsurface.entity = r_refdef.scene.worldentity;
7100 rsurface.skeleton = NULL;
7101 rsurface.ent_skinnum = 0;
7102 rsurface.ent_qwskin = -1;
7103 rsurface.ent_shadertime = 0;
7104 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7105 if (rsurface.array_size < model->surfmesh.num_vertices)
7106 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
7107 rsurface.matrix = identitymatrix;
7108 rsurface.inversematrix = identitymatrix;
7109 rsurface.matrixscale = 1;
7110 rsurface.inversematrixscale = 1;
7111 R_EntityMatrix(&identitymatrix);
7112 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7113 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7114 rsurface.fograngerecip = r_refdef.fograngerecip;
7115 rsurface.fogheightfade = r_refdef.fogheightfade;
7116 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7117 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7118 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7119 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7120 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7121 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7122 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7123 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7124 rsurface.colormod[3] = 1;
7125 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);
7126 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7127 rsurface.frameblend[0].lerp = 1;
7128 rsurface.ent_alttextures = false;
7129 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7130 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7131 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7132 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
7133 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7134 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7135 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
7136 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7137 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7138 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
7139 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7140 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7141 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
7142 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7143 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7144 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
7145 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7146 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7147 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
7148 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7149 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7150 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
7151 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7152 rsurface.modelelement3i = model->surfmesh.data_element3i;
7153 rsurface.modelelement3s = model->surfmesh.data_element3s;
7154 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
7155 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
7156 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7157 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
7158 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
7159 rsurface.modelsurfaces = model->data_surfaces;
7160 rsurface.generatedvertex = false;
7161 rsurface.vertex3f = rsurface.modelvertex3f;
7162 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7163 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7164 rsurface.svector3f = rsurface.modelsvector3f;
7165 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7166 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7167 rsurface.tvector3f = rsurface.modeltvector3f;
7168 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7169 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7170 rsurface.normal3f = rsurface.modelnormal3f;
7171 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7172 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7173 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7176 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7178 dp_model_t *model = ent->model;
7179 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7181 rsurface.entity = (entity_render_t *)ent;
7182 rsurface.skeleton = ent->skeleton;
7183 rsurface.ent_skinnum = ent->skinnum;
7184 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;
7185 rsurface.ent_shadertime = ent->shadertime;
7186 rsurface.ent_flags = ent->flags;
7187 if (rsurface.array_size < model->surfmesh.num_vertices)
7188 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
7189 rsurface.matrix = ent->matrix;
7190 rsurface.inversematrix = ent->inversematrix;
7191 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7192 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7193 R_EntityMatrix(&rsurface.matrix);
7194 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7195 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7196 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7197 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7198 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7199 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7200 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7201 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7202 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7203 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7204 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7205 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7206 rsurface.colormod[3] = ent->alpha;
7207 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7208 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7209 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7210 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7211 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7212 if (ent->model->brush.submodel && !prepass)
7214 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7215 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7217 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7219 if (ent->animcache_vertex3f && !r_framedata_failed)
7221 rsurface.modelvertex3f = ent->animcache_vertex3f;
7222 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7223 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7224 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7226 else if (wanttangents)
7228 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7229 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
7230 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
7231 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7232 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
7234 else if (wantnormals)
7236 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7237 rsurface.modelsvector3f = NULL;
7238 rsurface.modeltvector3f = NULL;
7239 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7240 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
7244 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
7245 rsurface.modelsvector3f = NULL;
7246 rsurface.modeltvector3f = NULL;
7247 rsurface.modelnormal3f = NULL;
7248 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
7250 rsurface.modelvertex3f_bufferobject = 0;
7251 rsurface.modelvertex3f_bufferoffset = 0;
7252 rsurface.modelsvector3f_bufferobject = 0;
7253 rsurface.modelsvector3f_bufferoffset = 0;
7254 rsurface.modeltvector3f_bufferobject = 0;
7255 rsurface.modeltvector3f_bufferoffset = 0;
7256 rsurface.modelnormal3f_bufferobject = 0;
7257 rsurface.modelnormal3f_bufferoffset = 0;
7258 rsurface.generatedvertex = true;
7262 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7263 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
7264 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7265 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7266 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
7267 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7268 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7269 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
7270 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7271 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7272 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
7273 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7274 rsurface.generatedvertex = false;
7276 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7277 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
7278 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7279 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7280 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
7281 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7282 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7283 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
7284 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7285 rsurface.modelelement3i = model->surfmesh.data_element3i;
7286 rsurface.modelelement3s = model->surfmesh.data_element3s;
7287 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
7288 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
7289 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7290 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
7291 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
7292 rsurface.modelsurfaces = model->data_surfaces;
7293 rsurface.vertex3f = rsurface.modelvertex3f;
7294 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7295 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7296 rsurface.svector3f = rsurface.modelsvector3f;
7297 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7298 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7299 rsurface.tvector3f = rsurface.modeltvector3f;
7300 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7301 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7302 rsurface.normal3f = rsurface.modelnormal3f;
7303 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7304 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7305 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7308 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)
7310 rsurface.entity = r_refdef.scene.worldentity;
7311 rsurface.skeleton = NULL;
7312 rsurface.ent_skinnum = 0;
7313 rsurface.ent_qwskin = -1;
7314 rsurface.ent_shadertime = shadertime;
7315 rsurface.ent_flags = entflags;
7316 rsurface.modelnum_vertices = numvertices;
7317 rsurface.modelnum_triangles = numtriangles;
7318 if (rsurface.array_size < rsurface.modelnum_vertices)
7319 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
7320 rsurface.matrix = *matrix;
7321 rsurface.inversematrix = *inversematrix;
7322 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7323 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7324 R_EntityMatrix(&rsurface.matrix);
7325 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7326 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7327 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7328 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7329 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7330 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7331 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7332 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7333 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7334 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7335 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7336 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7337 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);
7338 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7339 rsurface.frameblend[0].lerp = 1;
7340 rsurface.ent_alttextures = false;
7341 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7342 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7345 rsurface.modelvertex3f = vertex3f;
7346 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
7347 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
7348 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
7350 else if (wantnormals)
7352 rsurface.modelvertex3f = vertex3f;
7353 rsurface.modelsvector3f = NULL;
7354 rsurface.modeltvector3f = NULL;
7355 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
7359 rsurface.modelvertex3f = vertex3f;
7360 rsurface.modelsvector3f = NULL;
7361 rsurface.modeltvector3f = NULL;
7362 rsurface.modelnormal3f = NULL;
7364 rsurface.modelvertex3f_bufferobject = 0;
7365 rsurface.modelvertex3f_bufferoffset = 0;
7366 rsurface.modelsvector3f_bufferobject = 0;
7367 rsurface.modelsvector3f_bufferoffset = 0;
7368 rsurface.modeltvector3f_bufferobject = 0;
7369 rsurface.modeltvector3f_bufferoffset = 0;
7370 rsurface.modelnormal3f_bufferobject = 0;
7371 rsurface.modelnormal3f_bufferoffset = 0;
7372 rsurface.generatedvertex = true;
7373 rsurface.modellightmapcolor4f = color4f;
7374 rsurface.modellightmapcolor4f_bufferobject = 0;
7375 rsurface.modellightmapcolor4f_bufferoffset = 0;
7376 rsurface.modeltexcoordtexture2f = texcoord2f;
7377 rsurface.modeltexcoordtexture2f_bufferobject = 0;
7378 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7379 rsurface.modeltexcoordlightmap2f = NULL;
7380 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
7381 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7382 rsurface.modelelement3i = element3i;
7383 rsurface.modelelement3s = element3s;
7384 rsurface.modelelement3i_bufferobject = 0;
7385 rsurface.modelelement3s_bufferobject = 0;
7386 rsurface.modellightmapoffsets = NULL;
7387 rsurface.modelsurfaces = NULL;
7388 rsurface.vertex3f = rsurface.modelvertex3f;
7389 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7390 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7391 rsurface.svector3f = rsurface.modelsvector3f;
7392 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7393 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7394 rsurface.tvector3f = rsurface.modeltvector3f;
7395 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7396 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7397 rsurface.normal3f = rsurface.modelnormal3f;
7398 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7399 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7400 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7402 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
7404 if ((wantnormals || wanttangents) && !normal3f)
7405 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7406 if (wanttangents && !svector3f)
7407 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);
7411 float RSurf_FogPoint(const float *v)
7413 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7414 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7415 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7416 float FogHeightFade = r_refdef.fogheightfade;
7418 unsigned int fogmasktableindex;
7419 if (r_refdef.fogplaneviewabove)
7420 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7422 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7423 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7424 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7427 float RSurf_FogVertex(const float *v)
7429 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7430 float FogPlaneViewDist = rsurface.fogplaneviewdist;
7431 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7432 float FogHeightFade = rsurface.fogheightfade;
7434 unsigned int fogmasktableindex;
7435 if (r_refdef.fogplaneviewabove)
7436 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7438 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7439 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7440 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7443 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
7444 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
7447 int texturesurfaceindex;
7452 const float *v1, *in_tc;
7454 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
7456 q3shaderinfo_deform_t *deform;
7457 // 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
7458 if (rsurface.generatedvertex)
7460 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
7461 generatenormals = true;
7462 for (i = 0;i < Q3MAXDEFORMS;i++)
7464 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
7466 generatetangents = true;
7467 generatenormals = true;
7469 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
7470 generatenormals = true;
7472 if (generatenormals && !rsurface.modelnormal3f)
7474 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
7475 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
7476 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
7477 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7479 if (generatetangents && !rsurface.modelsvector3f)
7481 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
7482 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
7483 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
7484 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
7485 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
7486 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
7487 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);
7490 rsurface.vertex3f = rsurface.modelvertex3f;
7491 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
7492 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
7493 rsurface.svector3f = rsurface.modelsvector3f;
7494 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
7495 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
7496 rsurface.tvector3f = rsurface.modeltvector3f;
7497 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
7498 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
7499 rsurface.normal3f = rsurface.modelnormal3f;
7500 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
7501 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
7502 // if vertices are deformed (sprite flares and things in maps, possibly
7503 // water waves, bulges and other deformations), generate them into
7504 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
7505 // (may be static model data or generated data for an animated model, or
7506 // the previous deform pass)
7507 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
7509 switch (deform->deform)
7512 case Q3DEFORM_PROJECTIONSHADOW:
7513 case Q3DEFORM_TEXT0:
7514 case Q3DEFORM_TEXT1:
7515 case Q3DEFORM_TEXT2:
7516 case Q3DEFORM_TEXT3:
7517 case Q3DEFORM_TEXT4:
7518 case Q3DEFORM_TEXT5:
7519 case Q3DEFORM_TEXT6:
7520 case Q3DEFORM_TEXT7:
7523 case Q3DEFORM_AUTOSPRITE:
7524 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
7525 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
7526 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
7527 VectorNormalize(newforward);
7528 VectorNormalize(newright);
7529 VectorNormalize(newup);
7530 // make deformed versions of only the model vertices used by the specified surfaces
7531 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7533 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7534 // a single autosprite surface can contain multiple sprites...
7535 for (j = 0;j < surface->num_vertices - 3;j += 4)
7537 VectorClear(center);
7538 for (i = 0;i < 4;i++)
7539 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
7540 VectorScale(center, 0.25f, center);
7541 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
7542 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
7543 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
7544 for (i = 0;i < 4;i++)
7546 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
7547 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
7550 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);
7551 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);
7553 rsurface.vertex3f = rsurface.array_deformedvertex3f;
7554 rsurface.vertex3f_bufferobject = 0;
7555 rsurface.vertex3f_bufferoffset = 0;
7556 rsurface.svector3f = rsurface.array_deformedsvector3f;
7557 rsurface.svector3f_bufferobject = 0;
7558 rsurface.svector3f_bufferoffset = 0;
7559 rsurface.tvector3f = rsurface.array_deformedtvector3f;
7560 rsurface.tvector3f_bufferobject = 0;
7561 rsurface.tvector3f_bufferoffset = 0;
7562 rsurface.normal3f = rsurface.array_deformednormal3f;
7563 rsurface.normal3f_bufferobject = 0;
7564 rsurface.normal3f_bufferoffset = 0;
7566 case Q3DEFORM_AUTOSPRITE2:
7567 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
7568 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
7569 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
7570 VectorNormalize(newforward);
7571 VectorNormalize(newright);
7572 VectorNormalize(newup);
7573 // make deformed versions of only the model vertices used by the specified surfaces
7574 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7576 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7577 const float *v1, *v2;
7587 memset(shortest, 0, sizeof(shortest));
7588 // a single autosprite surface can contain multiple sprites...
7589 for (j = 0;j < surface->num_vertices - 3;j += 4)
7591 VectorClear(center);
7592 for (i = 0;i < 4;i++)
7593 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
7594 VectorScale(center, 0.25f, center);
7595 // find the two shortest edges, then use them to define the
7596 // axis vectors for rotating around the central axis
7597 for (i = 0;i < 6;i++)
7599 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
7600 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
7602 Debug_PolygonBegin(NULL, 0);
7603 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
7604 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);
7605 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
7608 l = VectorDistance2(v1, v2);
7609 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
7611 l += (1.0f / 1024.0f);
7612 if (shortest[0].length2 > l || i == 0)
7614 shortest[1] = shortest[0];
7615 shortest[0].length2 = l;
7616 shortest[0].v1 = v1;
7617 shortest[0].v2 = v2;
7619 else if (shortest[1].length2 > l || i == 1)
7621 shortest[1].length2 = l;
7622 shortest[1].v1 = v1;
7623 shortest[1].v2 = v2;
7626 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
7627 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
7629 Debug_PolygonBegin(NULL, 0);
7630 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
7631 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);
7632 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
7635 // this calculates the right vector from the shortest edge
7636 // and the up vector from the edge midpoints
7637 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
7638 VectorNormalize(right);
7639 VectorSubtract(end, start, up);
7640 VectorNormalize(up);
7641 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
7642 VectorSubtract(rsurface.localvieworigin, center, forward);
7643 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
7644 VectorNegate(forward, forward);
7645 VectorReflect(forward, 0, up, forward);
7646 VectorNormalize(forward);
7647 CrossProduct(up, forward, newright);
7648 VectorNormalize(newright);
7650 Debug_PolygonBegin(NULL, 0);
7651 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);
7652 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
7653 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
7657 Debug_PolygonBegin(NULL, 0);
7658 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
7659 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
7660 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
7663 // rotate the quad around the up axis vector, this is made
7664 // especially easy by the fact we know the quad is flat,
7665 // so we only have to subtract the center position and
7666 // measure distance along the right vector, and then
7667 // multiply that by the newright vector and add back the
7669 // we also need to subtract the old position to undo the
7670 // displacement from the center, which we do with a
7671 // DotProduct, the subtraction/addition of center is also
7672 // optimized into DotProducts here
7673 l = DotProduct(right, center);
7674 for (i = 0;i < 4;i++)
7676 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
7677 f = DotProduct(right, v1) - l;
7678 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
7681 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);
7682 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);
7684 rsurface.vertex3f = rsurface.array_deformedvertex3f;
7685 rsurface.vertex3f_bufferobject = 0;
7686 rsurface.vertex3f_bufferoffset = 0;
7687 rsurface.svector3f = rsurface.array_deformedsvector3f;
7688 rsurface.svector3f_bufferobject = 0;
7689 rsurface.svector3f_bufferoffset = 0;
7690 rsurface.tvector3f = rsurface.array_deformedtvector3f;
7691 rsurface.tvector3f_bufferobject = 0;
7692 rsurface.tvector3f_bufferoffset = 0;
7693 rsurface.normal3f = rsurface.array_deformednormal3f;
7694 rsurface.normal3f_bufferobject = 0;
7695 rsurface.normal3f_bufferoffset = 0;
7697 case Q3DEFORM_NORMAL:
7698 // deform the normals to make reflections wavey
7699 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7701 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7702 for (j = 0;j < surface->num_vertices;j++)
7705 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
7706 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
7707 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
7708 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7709 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7710 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
7711 VectorNormalize(normal);
7713 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);
7715 rsurface.svector3f = rsurface.array_deformedsvector3f;
7716 rsurface.svector3f_bufferobject = 0;
7717 rsurface.svector3f_bufferoffset = 0;
7718 rsurface.tvector3f = rsurface.array_deformedtvector3f;
7719 rsurface.tvector3f_bufferobject = 0;
7720 rsurface.tvector3f_bufferoffset = 0;
7721 rsurface.normal3f = rsurface.array_deformednormal3f;
7722 rsurface.normal3f_bufferobject = 0;
7723 rsurface.normal3f_bufferoffset = 0;
7726 // deform vertex array to make wavey water and flags and such
7727 waveparms[0] = deform->waveparms[0];
7728 waveparms[1] = deform->waveparms[1];
7729 waveparms[2] = deform->waveparms[2];
7730 waveparms[3] = deform->waveparms[3];
7731 // this is how a divisor of vertex influence on deformation
7732 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
7733 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
7734 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7736 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7737 for (j = 0;j < surface->num_vertices;j++)
7739 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
7740 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
7741 // if the wavefunc depends on time, evaluate it per-vertex
7744 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
7745 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
7747 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
7750 rsurface.vertex3f = rsurface.array_deformedvertex3f;
7751 rsurface.vertex3f_bufferobject = 0;
7752 rsurface.vertex3f_bufferoffset = 0;
7754 case Q3DEFORM_BULGE:
7755 // deform vertex array to make the surface have moving bulges
7756 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7758 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7759 for (j = 0;j < surface->num_vertices;j++)
7761 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
7762 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
7765 rsurface.vertex3f = rsurface.array_deformedvertex3f;
7766 rsurface.vertex3f_bufferobject = 0;
7767 rsurface.vertex3f_bufferoffset = 0;
7770 // deform vertex array
7771 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
7772 VectorScale(deform->parms, scale, waveparms);
7773 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7775 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7776 for (j = 0;j < surface->num_vertices;j++)
7777 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
7779 rsurface.vertex3f = rsurface.array_deformedvertex3f;
7780 rsurface.vertex3f_bufferobject = 0;
7781 rsurface.vertex3f_bufferoffset = 0;
7785 // generate texcoords based on the chosen texcoord source
7786 switch(rsurface.texture->tcgen.tcgen)
7789 case Q3TCGEN_TEXTURE:
7790 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
7791 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
7792 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
7794 case Q3TCGEN_LIGHTMAP:
7795 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
7796 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7797 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7799 case Q3TCGEN_VECTOR:
7800 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7802 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7803 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)
7805 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
7806 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
7809 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7810 rsurface.texcoordtexture2f_bufferobject = 0;
7811 rsurface.texcoordtexture2f_bufferoffset = 0;
7813 case Q3TCGEN_ENVIRONMENT:
7814 // make environment reflections using a spheremap
7815 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7817 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7818 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
7819 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
7820 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
7821 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
7823 // identical to Q3A's method, but executed in worldspace so
7824 // carried models can be shiny too
7826 float viewer[3], d, reflected[3], worldreflected[3];
7828 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
7829 // VectorNormalize(viewer);
7831 d = DotProduct(normal, viewer);
7833 reflected[0] = normal[0]*2*d - viewer[0];
7834 reflected[1] = normal[1]*2*d - viewer[1];
7835 reflected[2] = normal[2]*2*d - viewer[2];
7836 // note: this is proportinal to viewer, so we can normalize later
7838 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
7839 VectorNormalize(worldreflected);
7841 // note: this sphere map only uses world x and z!
7842 // so positive and negative y will LOOK THE SAME.
7843 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
7844 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
7847 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7848 rsurface.texcoordtexture2f_bufferobject = 0;
7849 rsurface.texcoordtexture2f_bufferoffset = 0;
7852 // the only tcmod that needs software vertex processing is turbulent, so
7853 // check for it here and apply the changes if needed
7854 // and we only support that as the first one
7855 // (handling a mixture of turbulent and other tcmods would be problematic
7856 // without punting it entirely to a software path)
7857 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
7859 amplitude = rsurface.texture->tcmods[0].parms[1];
7860 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
7861 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7863 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7864 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)
7866 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7867 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
7870 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
7871 rsurface.texcoordtexture2f_bufferobject = 0;
7872 rsurface.texcoordtexture2f_bufferoffset = 0;
7874 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
7875 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
7876 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
7877 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
7880 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7883 const msurface_t *surface = texturesurfacelist[0];
7884 const msurface_t *surface2;
7889 // TODO: lock all array ranges before render, rather than on each surface
7890 if (texturenumsurfaces == 1)
7892 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7893 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);
7895 else if (r_batchmode.integer == 2)
7897 #define MAXBATCHTRIANGLES 4096
7898 int batchtriangles = 0;
7899 static int batchelements[MAXBATCHTRIANGLES*3];
7900 for (i = 0;i < texturenumsurfaces;i = j)
7902 surface = texturesurfacelist[i];
7904 if (surface->num_triangles > MAXBATCHTRIANGLES)
7906 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);
7909 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
7910 batchtriangles = surface->num_triangles;
7911 firstvertex = surface->num_firstvertex;
7912 endvertex = surface->num_firstvertex + surface->num_vertices;
7913 for (;j < texturenumsurfaces;j++)
7915 surface2 = texturesurfacelist[j];
7916 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
7918 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
7919 batchtriangles += surface2->num_triangles;
7920 firstvertex = min(firstvertex, surface2->num_firstvertex);
7921 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
7923 surface2 = texturesurfacelist[j-1];
7924 numvertices = endvertex - firstvertex;
7925 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
7928 else if (r_batchmode.integer == 1)
7930 for (i = 0;i < texturenumsurfaces;i = j)
7932 surface = texturesurfacelist[i];
7933 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
7934 if (texturesurfacelist[j] != surface2)
7936 surface2 = texturesurfacelist[j-1];
7937 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
7938 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
7939 GL_LockArrays(surface->num_firstvertex, numvertices);
7940 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7945 for (i = 0;i < texturenumsurfaces;i++)
7947 surface = texturesurfacelist[i];
7948 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7949 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);
7954 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
7956 switch(vid.renderpath)
7958 case RENDERPATH_CGGL:
7960 if (r_cg_permutation->fp_Texture_Lightmap ) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Lightmap , R_GetTexture(surface->lightmaptexture ));
7961 if (r_cg_permutation->fp_Texture_Deluxemap) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Deluxemap, R_GetTexture(surface->deluxemaptexture));
7964 case RENDERPATH_GL20:
7965 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , R_GetTexture(surface->lightmaptexture ));
7966 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, R_GetTexture(surface->deluxemaptexture));
7968 case RENDERPATH_GL13:
7969 case RENDERPATH_GL11:
7970 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
7975 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
7977 // pick the closest matching water plane and bind textures
7978 int planeindex, vertexindex;
7982 r_waterstate_waterplane_t *p, *bestp;
7985 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7988 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
7990 Matrix4x4_Transform(&rsurface.matrix, v, vert);
7991 d += fabs(PlaneDiff(vert, &p->plane));
7993 if (bestd > d || !bestp)
7999 switch(vid.renderpath)
8001 case RENDERPATH_CGGL:
8003 if (r_cg_permutation->fp_Texture_Refraction >= 0) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Refraction, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));
8004 if (r_cg_permutation->fp_Texture_Reflection >= 0) cgGLSetTextureParameter(r_cg_permutation->fp_Texture_Reflection, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));
8007 case RENDERPATH_GL20:
8008 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? R_GetTexture(bestp->texture_refraction) : R_GetTexture(r_texture_black));
8009 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? R_GetTexture(bestp->texture_reflection) : R_GetTexture(r_texture_black));
8011 case RENDERPATH_GL13:
8012 case RENDERPATH_GL11:
8017 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8020 const msurface_t *surface;
8021 if (r_waterstate.renderingscene)
8023 for (i = 0;i < texturenumsurfaces;i++)
8025 surface = texturesurfacelist[i];
8026 RSurf_BindLightmapForSurface(surface);
8027 RSurf_BindReflectionForSurface(surface);
8028 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8029 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);
8033 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8037 const msurface_t *surface = texturesurfacelist[0];
8038 const msurface_t *surface2;
8043 if (texturenumsurfaces == 1)
8045 RSurf_BindLightmapForSurface(surface);
8046 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8047 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);
8049 else if (r_batchmode.integer == 2)
8051 #define MAXBATCHTRIANGLES 4096
8052 int batchtriangles = 0;
8053 static int batchelements[MAXBATCHTRIANGLES*3];
8054 for (i = 0;i < texturenumsurfaces;i = j)
8056 surface = texturesurfacelist[i];
8057 RSurf_BindLightmapForSurface(surface);
8059 if (surface->num_triangles > MAXBATCHTRIANGLES)
8061 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);
8064 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
8065 batchtriangles = surface->num_triangles;
8066 firstvertex = surface->num_firstvertex;
8067 endvertex = surface->num_firstvertex + surface->num_vertices;
8068 for (;j < texturenumsurfaces;j++)
8070 surface2 = texturesurfacelist[j];
8071 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
8073 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
8074 batchtriangles += surface2->num_triangles;
8075 firstvertex = min(firstvertex, surface2->num_firstvertex);
8076 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
8078 surface2 = texturesurfacelist[j-1];
8079 numvertices = endvertex - firstvertex;
8080 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
8083 else if (r_batchmode.integer == 1)
8086 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
8087 for (i = 0;i < texturenumsurfaces;i = j)
8089 surface = texturesurfacelist[i];
8090 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
8091 if (texturesurfacelist[j] != surface2)
8093 Con_Printf(" %i", j - i);
8096 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
8098 for (i = 0;i < texturenumsurfaces;i = j)
8100 surface = texturesurfacelist[i];
8101 RSurf_BindLightmapForSurface(surface);
8102 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
8103 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
8106 Con_Printf(" %i", j - i);
8108 surface2 = texturesurfacelist[j-1];
8109 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
8110 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
8111 GL_LockArrays(surface->num_firstvertex, numvertices);
8112 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
8120 for (i = 0;i < texturenumsurfaces;i++)
8122 surface = texturesurfacelist[i];
8123 RSurf_BindLightmapForSurface(surface);
8124 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8125 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);
8130 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8133 int texturesurfaceindex;
8134 if (r_showsurfaces.integer == 2)
8136 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8138 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8139 for (j = 0;j < surface->num_triangles;j++)
8141 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
8142 GL_Color(f, f, f, 1);
8143 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
8149 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8151 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8152 int k = (int)(((size_t)surface) / sizeof(msurface_t));
8153 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);
8154 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
8155 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);
8160 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8162 int texturesurfaceindex;
8166 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8168 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8169 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)
8177 rsurface.lightmapcolor4f = rsurface.array_color4f;
8178 rsurface.lightmapcolor4f_bufferobject = 0;
8179 rsurface.lightmapcolor4f_bufferoffset = 0;
8182 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8184 int texturesurfaceindex;
8190 if (rsurface.lightmapcolor4f)
8192 // generate color arrays for the surfaces in this list
8193 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8195 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8196 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)
8198 f = RSurf_FogVertex(v);
8208 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8210 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8211 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)
8213 f = RSurf_FogVertex(v);
8221 rsurface.lightmapcolor4f = rsurface.array_color4f;
8222 rsurface.lightmapcolor4f_bufferobject = 0;
8223 rsurface.lightmapcolor4f_bufferoffset = 0;
8226 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8228 int texturesurfaceindex;
8234 if (!rsurface.lightmapcolor4f)
8236 // generate color arrays for the surfaces in this list
8237 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8239 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8240 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)
8242 f = RSurf_FogVertex(v);
8243 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8244 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8245 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8249 rsurface.lightmapcolor4f = rsurface.array_color4f;
8250 rsurface.lightmapcolor4f_bufferobject = 0;
8251 rsurface.lightmapcolor4f_bufferoffset = 0;
8254 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
8256 int texturesurfaceindex;
8260 if (!rsurface.lightmapcolor4f)
8262 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8264 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8265 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)
8273 rsurface.lightmapcolor4f = rsurface.array_color4f;
8274 rsurface.lightmapcolor4f_bufferobject = 0;
8275 rsurface.lightmapcolor4f_bufferoffset = 0;
8278 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8280 int texturesurfaceindex;
8284 if (!rsurface.lightmapcolor4f)
8286 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8288 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8289 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)
8291 c2[0] = c[0] + r_refdef.scene.ambient;
8292 c2[1] = c[1] + r_refdef.scene.ambient;
8293 c2[2] = c[2] + r_refdef.scene.ambient;
8297 rsurface.lightmapcolor4f = rsurface.array_color4f;
8298 rsurface.lightmapcolor4f_bufferobject = 0;
8299 rsurface.lightmapcolor4f_bufferoffset = 0;
8302 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8305 rsurface.lightmapcolor4f = NULL;
8306 rsurface.lightmapcolor4f_bufferobject = 0;
8307 rsurface.lightmapcolor4f_bufferoffset = 0;
8308 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8309 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8310 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8311 GL_Color(r, g, b, a);
8312 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
8315 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8317 // TODO: optimize applyfog && applycolor case
8318 // just apply fog if necessary, and tint the fog color array if necessary
8319 rsurface.lightmapcolor4f = NULL;
8320 rsurface.lightmapcolor4f_bufferobject = 0;
8321 rsurface.lightmapcolor4f_bufferoffset = 0;
8322 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8323 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8324 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8325 GL_Color(r, g, b, a);
8326 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8329 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8331 int texturesurfaceindex;
8335 if (texturesurfacelist[0]->lightmapinfo)
8337 // generate color arrays for the surfaces in this list
8338 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8340 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8341 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
8343 if (surface->lightmapinfo->samples)
8345 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
8346 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
8347 VectorScale(lm, scale, c);
8348 if (surface->lightmapinfo->styles[1] != 255)
8350 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8352 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
8353 VectorMA(c, scale, lm, c);
8354 if (surface->lightmapinfo->styles[2] != 255)
8357 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
8358 VectorMA(c, scale, lm, c);
8359 if (surface->lightmapinfo->styles[3] != 255)
8362 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
8363 VectorMA(c, scale, lm, c);
8373 rsurface.lightmapcolor4f = rsurface.array_color4f;
8374 rsurface.lightmapcolor4f_bufferobject = 0;
8375 rsurface.lightmapcolor4f_bufferoffset = 0;
8379 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8380 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8381 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8383 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8384 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8385 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8386 GL_Color(r, g, b, a);
8387 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8390 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
8392 int texturesurfaceindex;
8399 vec3_t ambientcolor;
8400 vec3_t diffusecolor;
8404 VectorCopy(rsurface.modellight_lightdir, lightdir);
8405 f = 0.5f * r_refdef.lightmapintensity;
8406 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
8407 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
8408 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
8409 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
8410 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
8411 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
8413 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
8415 // generate color arrays for the surfaces in this list
8416 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8418 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8419 int numverts = surface->num_vertices;
8420 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
8421 n = rsurface.normal3f + 3 * surface->num_firstvertex;
8422 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
8423 // q3-style directional shading
8424 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
8426 if ((f = DotProduct(n, lightdir)) > 0)
8427 VectorMA(ambientcolor, f, diffusecolor, c);
8429 VectorCopy(ambientcolor, c);
8437 rsurface.lightmapcolor4f = rsurface.array_color4f;
8438 rsurface.lightmapcolor4f_bufferobject = 0;
8439 rsurface.lightmapcolor4f_bufferoffset = 0;
8440 *applycolor = false;
8444 *r = ambientcolor[0];
8445 *g = ambientcolor[1];
8446 *b = ambientcolor[2];
8447 rsurface.lightmapcolor4f = NULL;
8448 rsurface.lightmapcolor4f_bufferobject = 0;
8449 rsurface.lightmapcolor4f_bufferoffset = 0;
8453 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
8455 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
8456 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
8457 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
8458 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8459 GL_Color(r, g, b, a);
8460 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8463 void RSurf_SetupDepthAndCulling(void)
8465 // submodels are biased to avoid z-fighting with world surfaces that they
8466 // may be exactly overlapping (avoids z-fighting artifacts on certain
8467 // doors and things in Quake maps)
8468 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
8469 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
8470 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
8471 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
8474 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
8476 // transparent sky would be ridiculous
8477 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
8479 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8480 skyrenderlater = true;
8481 RSurf_SetupDepthAndCulling();
8483 // LordHavoc: HalfLife maps have freaky skypolys so don't use
8484 // skymasking on them, and Quake3 never did sky masking (unlike
8485 // software Quake and software Quake2), so disable the sky masking
8486 // in Quake3 maps as it causes problems with q3map2 sky tricks,
8487 // and skymasking also looks very bad when noclipping outside the
8488 // level, so don't use it then either.
8489 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
8491 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
8492 R_Mesh_ColorPointer(NULL, 0, 0);
8493 R_Mesh_ResetTextureState();
8494 if (skyrendermasked)
8496 R_SetupShader_DepthOrShadow();
8497 // depth-only (masking)
8498 GL_ColorMask(0,0,0,0);
8499 // just to make sure that braindead drivers don't draw
8500 // anything despite that colormask...
8501 GL_BlendFunc(GL_ZERO, GL_ONE);
8505 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8507 GL_BlendFunc(GL_ONE, GL_ZERO);
8509 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8510 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8511 if (skyrendermasked)
8512 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8514 R_Mesh_ResetTextureState();
8515 GL_Color(1, 1, 1, 1);
8518 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
8519 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
8520 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8522 qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
8523 qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
8525 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
8528 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
8529 R_Mesh_ColorPointer(NULL, 0, 0);
8531 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
8535 // render background
8536 GL_BlendFunc(GL_ONE, GL_ZERO);
8538 GL_AlphaTest(false);
8540 GL_Color(1, 1, 1, 1);
8541 R_Mesh_ColorPointer(NULL, 0, 0);
8543 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
8544 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
8545 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8546 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
8547 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
8548 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
8549 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8550 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8551 GL_LockArrays(0, 0);
8553 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
8554 GL_DepthMask(false);
8555 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
8556 R_Mesh_ColorPointer(NULL, 0, 0);
8558 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
8561 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
8563 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
8564 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8565 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
8566 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
8567 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
8569 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8573 GL_BlendFunc(GL_ONE, GL_ZERO);
8575 GL_AlphaTest(false);
8579 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
8580 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
8581 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
8584 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8586 if (refract || reflect)
8587 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8589 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
8593 if (refract || reflect)
8594 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
8596 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8598 GL_LockArrays(0, 0);
8601 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8603 // OpenGL 1.3 path - anything not completely ancient
8604 int texturesurfaceindex;
8605 qboolean applycolor;
8608 const texturelayer_t *layer;
8609 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8611 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
8614 int layertexrgbscale;
8615 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8617 if (layerindex == 0)
8621 GL_AlphaTest(false);
8622 qglDepthFunc(GL_EQUAL);CHECKGLERROR
8625 GL_DepthMask(layer->depthmask && writedepth);
8626 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
8627 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
8629 layertexrgbscale = 4;
8630 VectorScale(layer->color, 0.25f, layercolor);
8632 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
8634 layertexrgbscale = 2;
8635 VectorScale(layer->color, 0.5f, layercolor);
8639 layertexrgbscale = 1;
8640 VectorScale(layer->color, 1.0f, layercolor);
8642 layercolor[3] = layer->color[3];
8643 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
8644 R_Mesh_ColorPointer(NULL, 0, 0);
8645 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
8646 switch (layer->type)
8648 case TEXTURELAYERTYPE_LITTEXTURE:
8649 // single-pass lightmapped texture with 2x rgbscale
8650 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8651 R_Mesh_TexMatrix(0, NULL);
8652 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8653 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8654 R_Mesh_TexBind(1, R_GetTexture(layer->texture));
8655 R_Mesh_TexMatrix(1, &layer->texmatrix);
8656 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8657 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8658 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8659 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8660 else if (rsurface.uselightmaptexture)
8661 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8663 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8665 case TEXTURELAYERTYPE_TEXTURE:
8666 // singletexture unlit texture with transparency support
8667 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8668 R_Mesh_TexMatrix(0, &layer->texmatrix);
8669 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8670 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8671 R_Mesh_TexBind(1, 0);
8672 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
8673 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
8675 case TEXTURELAYERTYPE_FOG:
8676 // singletexture fogging
8679 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8680 R_Mesh_TexMatrix(0, &layer->texmatrix);
8681 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
8682 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8686 R_Mesh_TexBind(0, 0);
8687 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8689 R_Mesh_TexBind(1, 0);
8690 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
8691 // generate a color array for the fog pass
8692 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8693 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8699 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8700 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)
8702 f = 1 - RSurf_FogVertex(v);
8703 c[0] = layercolor[0];
8704 c[1] = layercolor[1];
8705 c[2] = layercolor[2];
8706 c[3] = f * layercolor[3];
8709 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8712 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8714 GL_LockArrays(0, 0);
8717 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8719 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8720 GL_AlphaTest(false);
8724 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8726 // OpenGL 1.1 - crusty old voodoo path
8727 int texturesurfaceindex;
8730 const texturelayer_t *layer;
8731 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8733 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
8735 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8737 if (layerindex == 0)
8741 GL_AlphaTest(false);
8742 qglDepthFunc(GL_EQUAL);CHECKGLERROR
8745 GL_DepthMask(layer->depthmask && writedepth);
8746 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
8747 R_Mesh_ColorPointer(NULL, 0, 0);
8748 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
8749 switch (layer->type)
8751 case TEXTURELAYERTYPE_LITTEXTURE:
8752 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
8754 // two-pass lit texture with 2x rgbscale
8755 // first the lightmap pass
8756 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8757 R_Mesh_TexMatrix(0, NULL);
8758 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8759 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
8760 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8761 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8762 else if (rsurface.uselightmaptexture)
8763 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8765 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
8766 GL_LockArrays(0, 0);
8767 // then apply the texture to it
8768 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8769 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8770 R_Mesh_TexMatrix(0, &layer->texmatrix);
8771 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8772 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8773 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);
8777 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
8778 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8779 R_Mesh_TexMatrix(0, &layer->texmatrix);
8780 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8781 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8782 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8783 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);
8785 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);
8788 case TEXTURELAYERTYPE_TEXTURE:
8789 // singletexture unlit texture with transparency support
8790 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8791 R_Mesh_TexMatrix(0, &layer->texmatrix);
8792 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8793 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8794 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);
8796 case TEXTURELAYERTYPE_FOG:
8797 // singletexture fogging
8800 R_Mesh_TexBind(0, R_GetTexture(layer->texture));
8801 R_Mesh_TexMatrix(0, &layer->texmatrix);
8802 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
8803 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
8807 R_Mesh_TexBind(0, 0);
8808 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
8810 // generate a color array for the fog pass
8811 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
8812 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
8818 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
8819 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)
8821 f = 1 - RSurf_FogVertex(v);
8822 c[0] = layer->color[0];
8823 c[1] = layer->color[1];
8824 c[2] = layer->color[2];
8825 c[3] = f * layer->color[3];
8828 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8831 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
8833 GL_LockArrays(0, 0);
8836 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8838 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
8839 GL_AlphaTest(false);
8843 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
8847 GL_AlphaTest(false);
8848 R_Mesh_ColorPointer(NULL, 0, 0);
8849 R_Mesh_ResetTextureState();
8850 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8852 if(rsurface.texture && rsurface.texture->currentskinframe)
8854 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
8855 c[3] *= rsurface.texture->currentalpha;
8865 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
8867 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
8868 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
8869 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
8872 // brighten it up (as texture value 127 means "unlit")
8873 c[0] *= 2 * r_refdef.view.colorscale;
8874 c[1] *= 2 * r_refdef.view.colorscale;
8875 c[2] *= 2 * r_refdef.view.colorscale;
8877 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
8878 c[3] *= r_wateralpha.value;
8880 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
8882 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8883 GL_DepthMask(false);
8885 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
8887 GL_BlendFunc(GL_ONE, GL_ONE);
8888 GL_DepthMask(false);
8890 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
8892 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
8893 GL_DepthMask(false);
8895 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8897 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
8898 GL_DepthMask(false);
8902 GL_BlendFunc(GL_ONE, GL_ZERO);
8903 GL_DepthMask(writedepth);
8906 rsurface.lightmapcolor4f = NULL;
8908 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8910 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8912 rsurface.lightmapcolor4f = NULL;
8913 rsurface.lightmapcolor4f_bufferobject = 0;
8914 rsurface.lightmapcolor4f_bufferoffset = 0;
8916 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8918 qboolean applycolor = true;
8921 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
8923 r_refdef.lightmapintensity = 1;
8924 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
8925 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
8929 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8931 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
8932 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
8933 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8936 if(!rsurface.lightmapcolor4f)
8937 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
8939 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
8940 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
8941 if(r_refdef.fogenabled)
8942 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
8944 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
8945 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8948 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8951 RSurf_SetupDepthAndCulling();
8952 if (r_showsurfaces.integer == 3 && !prepass)
8954 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8957 switch (vid.renderpath)
8959 case RENDERPATH_GL20:
8960 case RENDERPATH_CGGL:
8961 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8963 case RENDERPATH_GL13:
8964 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8966 case RENDERPATH_GL11:
8967 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8973 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
8976 RSurf_SetupDepthAndCulling();
8977 if (r_showsurfaces.integer == 3 && !prepass)
8979 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
8982 switch (vid.renderpath)
8984 case RENDERPATH_GL20:
8985 case RENDERPATH_CGGL:
8986 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
8988 case RENDERPATH_GL13:
8989 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
8991 case RENDERPATH_GL11:
8992 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
8998 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9001 int texturenumsurfaces, endsurface;
9003 const msurface_t *surface;
9004 const msurface_t *texturesurfacelist[256];
9006 // if the model is static it doesn't matter what value we give for
9007 // wantnormals and wanttangents, so this logic uses only rules applicable
9008 // to a model, knowing that they are meaningless otherwise
9009 if (ent == r_refdef.scene.worldentity)
9010 RSurf_ActiveWorldEntity();
9011 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9012 RSurf_ActiveModelEntity(ent, false, false, false);
9015 switch (vid.renderpath)
9017 case RENDERPATH_GL20:
9018 case RENDERPATH_CGGL:
9019 RSurf_ActiveModelEntity(ent, true, true, false);
9021 case RENDERPATH_GL13:
9022 case RENDERPATH_GL11:
9023 RSurf_ActiveModelEntity(ent, true, false, false);
9028 if (r_transparentdepthmasking.integer)
9030 qboolean setup = false;
9031 for (i = 0;i < numsurfaces;i = j)
9034 surface = rsurface.modelsurfaces + surfacelist[i];
9035 texture = surface->texture;
9036 rsurface.texture = R_GetCurrentTexture(texture);
9037 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9038 // scan ahead until we find a different texture
9039 endsurface = min(i + 1024, numsurfaces);
9040 texturenumsurfaces = 0;
9041 texturesurfacelist[texturenumsurfaces++] = surface;
9042 for (;j < endsurface;j++)
9044 surface = rsurface.modelsurfaces + surfacelist[j];
9045 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
9047 texturesurfacelist[texturenumsurfaces++] = surface;
9049 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9051 // render the range of surfaces as depth
9055 GL_ColorMask(0,0,0,0);
9058 GL_BlendFunc(GL_ONE, GL_ZERO);
9060 GL_AlphaTest(false);
9061 R_Mesh_ColorPointer(NULL, 0, 0);
9062 R_Mesh_ResetTextureState();
9063 R_SetupShader_DepthOrShadow();
9065 RSurf_SetupDepthAndCulling();
9066 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9067 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9070 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9073 for (i = 0;i < numsurfaces;i = j)
9076 surface = rsurface.modelsurfaces + surfacelist[i];
9077 texture = surface->texture;
9078 rsurface.texture = R_GetCurrentTexture(texture);
9079 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9080 // scan ahead until we find a different texture
9081 endsurface = min(i + 1024, numsurfaces);
9082 texturenumsurfaces = 0;
9083 texturesurfacelist[texturenumsurfaces++] = surface;
9084 for (;j < endsurface;j++)
9086 surface = rsurface.modelsurfaces + surfacelist[j];
9087 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
9089 texturesurfacelist[texturenumsurfaces++] = surface;
9091 // render the range of surfaces
9092 if (ent == r_refdef.scene.worldentity)
9093 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9095 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9097 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9098 GL_AlphaTest(false);
9101 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9103 // transparent surfaces get pushed off into the transparent queue
9104 int surfacelistindex;
9105 const msurface_t *surface;
9106 vec3_t tempcenter, center;
9107 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9109 surface = texturesurfacelist[surfacelistindex];
9110 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9111 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9112 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9113 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9114 if (queueentity->transparent_offset) // transparent offset
9116 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9117 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9118 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9120 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9124 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9126 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9130 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9132 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9134 RSurf_SetupDepthAndCulling();
9135 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9136 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9140 if (!rsurface.texture->currentnumlayers)
9142 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9143 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9145 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9147 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
9149 RSurf_SetupDepthAndCulling();
9150 GL_AlphaTest(false);
9151 R_Mesh_ColorPointer(NULL, 0, 0);
9152 R_Mesh_ResetTextureState();
9153 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9154 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9156 GL_BlendFunc(GL_ONE, GL_ZERO);
9157 GL_Color(0, 0, 0, 1);
9158 GL_DepthTest(writedepth);
9159 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9161 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
9163 RSurf_SetupDepthAndCulling();
9164 GL_AlphaTest(false);
9165 R_Mesh_ColorPointer(NULL, 0, 0);
9166 R_Mesh_ResetTextureState();
9167 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9168 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9170 GL_BlendFunc(GL_ONE, GL_ZERO);
9172 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
9174 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
9175 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9176 else if (!rsurface.texture->currentnumlayers)
9178 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9180 // in the deferred case, transparent surfaces were queued during prepass
9181 if (!r_shadow_usingdeferredprepass)
9182 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9186 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9187 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9192 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9196 // break the surface list down into batches by texture and use of lightmapping
9197 for (i = 0;i < numsurfaces;i = j)
9200 // texture is the base texture pointer, rsurface.texture is the
9201 // current frame/skin the texture is directing us to use (for example
9202 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9203 // use skin 1 instead)
9204 texture = surfacelist[i]->texture;
9205 rsurface.texture = R_GetCurrentTexture(texture);
9206 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
9207 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9209 // if this texture is not the kind we want, skip ahead to the next one
9210 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9214 // simply scan ahead until we find a different texture or lightmap state
9215 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
9217 // render the range of surfaces
9218 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
9222 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
9227 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9229 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9231 RSurf_SetupDepthAndCulling();
9232 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9233 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9237 if (!rsurface.texture->currentnumlayers)
9239 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9240 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9242 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9244 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
9246 RSurf_SetupDepthAndCulling();
9247 GL_AlphaTest(false);
9248 R_Mesh_ColorPointer(NULL, 0, 0);
9249 R_Mesh_ResetTextureState();
9250 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9251 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9253 GL_BlendFunc(GL_ONE, GL_ZERO);
9254 GL_Color(0, 0, 0, 1);
9255 GL_DepthTest(writedepth);
9256 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9258 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9260 RSurf_SetupDepthAndCulling();
9261 GL_AlphaTest(false);
9262 R_Mesh_ColorPointer(NULL, 0, 0);
9263 R_Mesh_ResetTextureState();
9264 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9265 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
9267 GL_BlendFunc(GL_ONE, GL_ZERO);
9269 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
9271 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
9272 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9273 else if (!rsurface.texture->currentnumlayers)
9275 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9277 // in the deferred case, transparent surfaces were queued during prepass
9278 if (!r_shadow_usingdeferredprepass)
9279 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9283 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9284 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9289 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9293 // break the surface list down into batches by texture and use of lightmapping
9294 for (i = 0;i < numsurfaces;i = j)
9297 // texture is the base texture pointer, rsurface.texture is the
9298 // current frame/skin the texture is directing us to use (for example
9299 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9300 // use skin 1 instead)
9301 texture = surfacelist[i]->texture;
9302 rsurface.texture = R_GetCurrentTexture(texture);
9303 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
9304 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9306 // if this texture is not the kind we want, skip ahead to the next one
9307 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9311 // simply scan ahead until we find a different texture or lightmap state
9312 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
9314 // render the range of surfaces
9315 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
9319 float locboxvertex3f[6*4*3] =
9321 1,0,1, 1,0,0, 1,1,0, 1,1,1,
9322 0,1,1, 0,1,0, 0,0,0, 0,0,1,
9323 1,1,1, 1,1,0, 0,1,0, 0,1,1,
9324 0,0,1, 0,0,0, 1,0,0, 1,0,1,
9325 0,0,1, 1,0,1, 1,1,1, 0,1,1,
9326 1,0,0, 0,0,0, 0,1,0, 1,1,0
9329 unsigned short locboxelements[6*2*3] =
9339 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9342 cl_locnode_t *loc = (cl_locnode_t *)ent;
9344 float vertex3f[6*4*3];
9346 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9347 GL_DepthMask(false);
9348 GL_DepthRange(0, 1);
9349 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9351 GL_CullFace(GL_NONE);
9352 R_EntityMatrix(&identitymatrix);
9354 R_Mesh_VertexPointer(vertex3f, 0, 0);
9355 R_Mesh_ColorPointer(NULL, 0, 0);
9356 R_Mesh_ResetTextureState();
9357 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9360 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9361 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9362 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
9363 surfacelist[0] < 0 ? 0.5f : 0.125f);
9365 if (VectorCompare(loc->mins, loc->maxs))
9367 VectorSet(size, 2, 2, 2);
9368 VectorMA(loc->mins, -0.5f, size, mins);
9372 VectorCopy(loc->mins, mins);
9373 VectorSubtract(loc->maxs, loc->mins, size);
9376 for (i = 0;i < 6*4*3;)
9377 for (j = 0;j < 3;j++, i++)
9378 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
9380 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
9383 void R_DrawLocs(void)
9386 cl_locnode_t *loc, *nearestloc;
9388 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
9389 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
9391 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
9392 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
9396 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
9398 if (decalsystem->decals)
9399 Mem_Free(decalsystem->decals);
9400 memset(decalsystem, 0, sizeof(*decalsystem));
9403 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)
9410 // expand or initialize the system
9411 if (decalsystem->maxdecals <= decalsystem->numdecals)
9413 decalsystem_t old = *decalsystem;
9414 qboolean useshortelements;
9415 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
9416 useshortelements = decalsystem->maxdecals * 3 <= 65536;
9417 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)));
9418 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
9419 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
9420 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
9421 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
9422 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
9423 if (decalsystem->numdecals)
9424 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
9426 Mem_Free(old.decals);
9427 for (i = 0;i < decalsystem->maxdecals*3;i++)
9428 decalsystem->element3i[i] = i;
9429 if (useshortelements)
9430 for (i = 0;i < decalsystem->maxdecals*3;i++)
9431 decalsystem->element3s[i] = i;
9434 // grab a decal and search for another free slot for the next one
9435 maxdecals = decalsystem->maxdecals;
9436 decals = decalsystem->decals;
9437 decal = decalsystem->decals + (i = decalsystem->freedecal++);
9438 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
9440 decalsystem->freedecal = i;
9441 if (decalsystem->numdecals <= i)
9442 decalsystem->numdecals = i + 1;
9444 // initialize the decal
9446 decal->triangleindex = triangleindex;
9447 decal->surfaceindex = surfaceindex;
9448 decal->decalsequence = decalsequence;
9449 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
9450 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
9451 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
9452 decal->color4ub[0][3] = 255;
9453 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
9454 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
9455 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
9456 decal->color4ub[1][3] = 255;
9457 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
9458 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
9459 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
9460 decal->color4ub[2][3] = 255;
9461 decal->vertex3f[0][0] = v0[0];
9462 decal->vertex3f[0][1] = v0[1];
9463 decal->vertex3f[0][2] = v0[2];
9464 decal->vertex3f[1][0] = v1[0];
9465 decal->vertex3f[1][1] = v1[1];
9466 decal->vertex3f[1][2] = v1[2];
9467 decal->vertex3f[2][0] = v2[0];
9468 decal->vertex3f[2][1] = v2[1];
9469 decal->vertex3f[2][2] = v2[2];
9470 decal->texcoord2f[0][0] = t0[0];
9471 decal->texcoord2f[0][1] = t0[1];
9472 decal->texcoord2f[1][0] = t1[0];
9473 decal->texcoord2f[1][1] = t1[1];
9474 decal->texcoord2f[2][0] = t2[0];
9475 decal->texcoord2f[2][1] = t2[1];
9478 extern cvar_t cl_decals_bias;
9479 extern cvar_t cl_decals_models;
9480 extern cvar_t cl_decals_newsystem_intensitymultiplier;
9481 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)
9483 matrix4x4_t projection;
9484 decalsystem_t *decalsystem;
9487 const float *vertex3f;
9488 const msurface_t *surface;
9489 const msurface_t *surfaces;
9490 const int *surfacelist;
9491 const texture_t *texture;
9495 int surfacelistindex;
9498 int decalsurfaceindex;
9503 float localorigin[3];
9504 float localnormal[3];
9515 float points[2][9][3];
9519 decalsystem = &ent->decalsystem;
9521 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
9523 R_DecalSystem_Reset(&ent->decalsystem);
9527 if (!model->brush.data_nodes && !cl_decals_models.integer)
9529 if (decalsystem->model)
9530 R_DecalSystem_Reset(decalsystem);
9534 if (decalsystem->model != model)
9535 R_DecalSystem_Reset(decalsystem);
9536 decalsystem->model = model;
9538 RSurf_ActiveModelEntity(ent, false, false, false);
9540 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
9541 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
9542 VectorNormalize(localnormal);
9543 localsize = worldsize*rsurface.inversematrixscale;
9544 ilocalsize = 1.0f / localsize;
9545 localmins[0] = localorigin[0] - localsize;
9546 localmins[1] = localorigin[1] - localsize;
9547 localmins[2] = localorigin[2] - localsize;
9548 localmaxs[0] = localorigin[0] + localsize;
9549 localmaxs[1] = localorigin[1] + localsize;
9550 localmaxs[2] = localorigin[2] + localsize;
9552 //VectorCopy(localnormal, planes[4]);
9553 //VectorVectors(planes[4], planes[2], planes[0]);
9554 AnglesFromVectors(angles, localnormal, NULL, false);
9555 AngleVectors(angles, planes[0], planes[2], planes[4]);
9556 VectorNegate(planes[0], planes[1]);
9557 VectorNegate(planes[2], planes[3]);
9558 VectorNegate(planes[4], planes[5]);
9559 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
9560 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
9561 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
9562 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
9563 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
9564 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
9569 matrix4x4_t forwardprojection;
9570 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
9571 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
9576 float projectionvector[4][3];
9577 VectorScale(planes[0], ilocalsize, projectionvector[0]);
9578 VectorScale(planes[2], ilocalsize, projectionvector[1]);
9579 VectorScale(planes[4], ilocalsize, projectionvector[2]);
9580 projectionvector[0][0] = planes[0][0] * ilocalsize;
9581 projectionvector[0][1] = planes[1][0] * ilocalsize;
9582 projectionvector[0][2] = planes[2][0] * ilocalsize;
9583 projectionvector[1][0] = planes[0][1] * ilocalsize;
9584 projectionvector[1][1] = planes[1][1] * ilocalsize;
9585 projectionvector[1][2] = planes[2][1] * ilocalsize;
9586 projectionvector[2][0] = planes[0][2] * ilocalsize;
9587 projectionvector[2][1] = planes[1][2] * ilocalsize;
9588 projectionvector[2][2] = planes[2][2] * ilocalsize;
9589 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
9590 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
9591 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
9592 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
9596 dynamic = model->surfmesh.isanimated;
9597 vertex3f = rsurface.modelvertex3f;
9598 numsurfacelist = model->nummodelsurfaces;
9599 surfacelist = model->sortedmodelsurfaces;
9600 surfaces = model->data_surfaces;
9601 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
9603 surfaceindex = surfacelist[surfacelistindex];
9604 surface = surfaces + surfaceindex;
9605 // skip transparent surfaces
9606 texture = surface->texture;
9607 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
9609 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
9611 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
9613 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
9614 numvertices = surface->num_vertices;
9615 numtriangles = surface->num_triangles;
9616 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
9618 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9620 index = 3*e[cornerindex];
9621 VectorCopy(vertex3f + index, v[cornerindex]);
9624 //TriangleNormal(v[0], v[1], v[2], normal);
9625 //if (DotProduct(normal, localnormal) < 0.0f)
9627 // clip by each of the box planes formed from the projection matrix
9628 // if anything survives, we emit the decal
9629 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]);
9632 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]);
9635 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]);
9638 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]);
9641 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]);
9644 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]);
9647 // some part of the triangle survived, so we have to accept it...
9650 // dynamic always uses the original triangle
9652 for (cornerindex = 0;cornerindex < 3;cornerindex++)
9654 index = 3*e[cornerindex];
9655 VectorCopy(vertex3f + index, v[cornerindex]);
9658 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
9660 // convert vertex positions to texcoords
9661 Matrix4x4_Transform(&projection, v[cornerindex], temp);
9662 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
9663 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
9664 // calculate distance fade from the projection origin
9665 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
9666 f = bound(0.0f, f, 1.0f);
9667 c[cornerindex][0] = r * f;
9668 c[cornerindex][1] = g * f;
9669 c[cornerindex][2] = b * f;
9670 c[cornerindex][3] = 1.0f;
9671 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
9674 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);
9676 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
9677 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);
9682 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
9683 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)
9685 int renderentityindex;
9688 entity_render_t *ent;
9690 if (!cl_decals_newsystem.integer)
9693 worldmins[0] = worldorigin[0] - worldsize;
9694 worldmins[1] = worldorigin[1] - worldsize;
9695 worldmins[2] = worldorigin[2] - worldsize;
9696 worldmaxs[0] = worldorigin[0] + worldsize;
9697 worldmaxs[1] = worldorigin[1] + worldsize;
9698 worldmaxs[2] = worldorigin[2] + worldsize;
9700 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9702 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
9704 ent = r_refdef.scene.entities[renderentityindex];
9705 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
9708 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
9712 typedef struct r_decalsystem_splatqueue_s
9721 r_decalsystem_splatqueue_t;
9723 int r_decalsystem_numqueued = 0;
9724 #define MAX_DECALSYSTEM_QUEUE 1024
9725 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
9727 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)
9729 r_decalsystem_splatqueue_t *queue;
9731 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
9734 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
9735 VectorCopy(worldorigin, queue->worldorigin);
9736 VectorCopy(worldnormal, queue->worldnormal);
9737 Vector4Set(queue->color, r, g, b, a);
9738 Vector4Set(queue->tcrange, s1, t1, s2, t2);
9739 queue->worldsize = worldsize;
9740 queue->decalsequence = cl.decalsequence++;
9743 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
9746 r_decalsystem_splatqueue_t *queue;
9748 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
9749 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);
9750 r_decalsystem_numqueued = 0;
9753 extern cvar_t cl_decals_max;
9754 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
9757 decalsystem_t *decalsystem = &ent->decalsystem;
9764 if (!decalsystem->numdecals)
9767 if (r_showsurfaces.integer)
9770 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9772 R_DecalSystem_Reset(decalsystem);
9776 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
9777 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
9779 if (decalsystem->lastupdatetime)
9780 frametime = (cl.time - decalsystem->lastupdatetime);
9783 decalsystem->lastupdatetime = cl.time;
9784 decal = decalsystem->decals;
9785 numdecals = decalsystem->numdecals;
9787 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9789 if (decal->color4ub[0][3])
9791 decal->lived += frametime;
9792 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
9794 memset(decal, 0, sizeof(*decal));
9795 if (decalsystem->freedecal > i)
9796 decalsystem->freedecal = i;
9800 decal = decalsystem->decals;
9801 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
9804 // collapse the array by shuffling the tail decals into the gaps
9807 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
9808 decalsystem->freedecal++;
9809 if (decalsystem->freedecal == numdecals)
9811 decal[decalsystem->freedecal] = decal[--numdecals];
9814 decalsystem->numdecals = numdecals;
9818 // if there are no decals left, reset decalsystem
9819 R_DecalSystem_Reset(decalsystem);
9823 extern skinframe_t *decalskinframe;
9824 static void R_DrawModelDecals_Entity(entity_render_t *ent)
9827 decalsystem_t *decalsystem = &ent->decalsystem;
9837 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
9840 numdecals = decalsystem->numdecals;
9844 if (r_showsurfaces.integer)
9847 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
9849 R_DecalSystem_Reset(decalsystem);
9853 // if the model is static it doesn't matter what value we give for
9854 // wantnormals and wanttangents, so this logic uses only rules applicable
9855 // to a model, knowing that they are meaningless otherwise
9856 if (ent == r_refdef.scene.worldentity)
9857 RSurf_ActiveWorldEntity();
9859 RSurf_ActiveModelEntity(ent, false, false, false);
9861 decalsystem->lastupdatetime = cl.time;
9862 decal = decalsystem->decals;
9864 fadedelay = cl_decals_time.value;
9865 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
9867 // update vertex positions for animated models
9868 v3f = decalsystem->vertex3f;
9869 c4f = decalsystem->color4f;
9870 t2f = decalsystem->texcoord2f;
9871 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
9873 if (!decal->color4ub[0][3])
9876 if (surfacevisible && !surfacevisible[decal->surfaceindex])
9879 // update color values for fading decals
9880 if (decal->lived >= cl_decals_time.value)
9882 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
9883 alpha *= (1.0f/255.0f);
9886 alpha = 1.0f/255.0f;
9888 c4f[ 0] = decal->color4ub[0][0] * alpha;
9889 c4f[ 1] = decal->color4ub[0][1] * alpha;
9890 c4f[ 2] = decal->color4ub[0][2] * alpha;
9892 c4f[ 4] = decal->color4ub[1][0] * alpha;
9893 c4f[ 5] = decal->color4ub[1][1] * alpha;
9894 c4f[ 6] = decal->color4ub[1][2] * alpha;
9896 c4f[ 8] = decal->color4ub[2][0] * alpha;
9897 c4f[ 9] = decal->color4ub[2][1] * alpha;
9898 c4f[10] = decal->color4ub[2][2] * alpha;
9901 t2f[0] = decal->texcoord2f[0][0];
9902 t2f[1] = decal->texcoord2f[0][1];
9903 t2f[2] = decal->texcoord2f[1][0];
9904 t2f[3] = decal->texcoord2f[1][1];
9905 t2f[4] = decal->texcoord2f[2][0];
9906 t2f[5] = decal->texcoord2f[2][1];
9908 // update vertex positions for animated models
9909 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
9911 e = rsurface.modelelement3i + 3*decal->triangleindex;
9912 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
9913 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
9914 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
9918 VectorCopy(decal->vertex3f[0], v3f);
9919 VectorCopy(decal->vertex3f[1], v3f + 3);
9920 VectorCopy(decal->vertex3f[2], v3f + 6);
9931 r_refdef.stats.drawndecals += numtris;
9933 if (r_refdef.fogenabled)
9935 switch(vid.renderpath)
9937 case RENDERPATH_GL20:
9938 case RENDERPATH_CGGL:
9939 case RENDERPATH_GL13:
9940 case RENDERPATH_GL11:
9941 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
9943 alpha = RSurf_FogVertex(v3f);
9952 // now render the decals all at once
9953 // (this assumes they all use one particle font texture!)
9954 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);
9955 R_Mesh_ResetTextureState();
9956 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
9957 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
9958 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
9959 GL_DepthMask(false);
9960 GL_DepthRange(0, 1);
9961 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
9963 GL_CullFace(GL_NONE);
9964 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
9965 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
9966 GL_LockArrays(0, numtris * 3);
9967 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
9968 GL_LockArrays(0, 0);
9972 static void R_DrawModelDecals(void)
9976 // fade faster when there are too many decals
9977 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9978 for (i = 0;i < r_refdef.scene.numentities;i++)
9979 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9981 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
9982 for (i = 0;i < r_refdef.scene.numentities;i++)
9983 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
9984 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
9986 R_DecalSystem_ApplySplatEntitiesQueue();
9988 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
9989 for (i = 0;i < r_refdef.scene.numentities;i++)
9990 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
9992 r_refdef.stats.totaldecals += numdecals;
9994 if (r_showsurfaces.integer)
9997 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
9999 for (i = 0;i < r_refdef.scene.numentities;i++)
10001 if (!r_refdef.viewcache.entityvisible[i])
10003 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10004 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10008 void R_DrawDebugModel(void)
10010 entity_render_t *ent = rsurface.entity;
10011 int i, j, k, l, flagsmask;
10012 const int *elements;
10014 const msurface_t *surface;
10015 dp_model_t *model = ent->model;
10018 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10020 R_Mesh_ColorPointer(NULL, 0, 0);
10021 R_Mesh_ResetTextureState();
10022 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10023 GL_DepthRange(0, 1);
10024 GL_DepthTest(!r_showdisabledepthtest.integer);
10025 GL_DepthMask(false);
10026 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10028 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
10030 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10031 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
10033 if (brush->colbrushf && brush->colbrushf->numtriangles)
10035 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
10036 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);
10037 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
10040 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
10042 if (surface->num_collisiontriangles)
10044 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
10045 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);
10046 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
10051 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10053 if (r_showtris.integer || r_shownormals.integer)
10055 if (r_showdisabledepthtest.integer)
10057 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10058 GL_DepthMask(false);
10062 GL_BlendFunc(GL_ONE, GL_ZERO);
10063 GL_DepthMask(true);
10065 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10067 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10069 rsurface.texture = R_GetCurrentTexture(surface->texture);
10070 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10072 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
10073 if (r_showtris.value > 0)
10075 if (!rsurface.texture->currentlayers->depthmask)
10076 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10077 else if (ent == r_refdef.scene.worldentity)
10078 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10080 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10081 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
10082 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
10083 R_Mesh_ColorPointer(NULL, 0, 0);
10084 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
10085 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10086 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
10087 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);
10088 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10091 if (r_shownormals.value < 0)
10093 qglBegin(GL_LINES);
10094 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10096 VectorCopy(rsurface.vertex3f + l * 3, v);
10097 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10098 qglVertex3f(v[0], v[1], v[2]);
10099 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
10100 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10101 qglVertex3f(v[0], v[1], v[2]);
10106 if (r_shownormals.value > 0)
10108 qglBegin(GL_LINES);
10109 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10111 VectorCopy(rsurface.vertex3f + l * 3, v);
10112 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10113 qglVertex3f(v[0], v[1], v[2]);
10114 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
10115 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10116 qglVertex3f(v[0], v[1], v[2]);
10120 qglBegin(GL_LINES);
10121 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10123 VectorCopy(rsurface.vertex3f + l * 3, v);
10124 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10125 qglVertex3f(v[0], v[1], v[2]);
10126 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
10127 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10128 qglVertex3f(v[0], v[1], v[2]);
10132 qglBegin(GL_LINES);
10133 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
10135 VectorCopy(rsurface.vertex3f + l * 3, v);
10136 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10137 qglVertex3f(v[0], v[1], v[2]);
10138 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
10139 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
10140 qglVertex3f(v[0], v[1], v[2]);
10147 rsurface.texture = NULL;
10151 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10152 int r_maxsurfacelist = 0;
10153 const msurface_t **r_surfacelist = NULL;
10154 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10156 int i, j, endj, f, flagsmask;
10158 dp_model_t *model = r_refdef.scene.worldmodel;
10159 msurface_t *surfaces;
10160 unsigned char *update;
10161 int numsurfacelist = 0;
10165 if (r_maxsurfacelist < model->num_surfaces)
10167 r_maxsurfacelist = model->num_surfaces;
10169 Mem_Free((msurface_t**)r_surfacelist);
10170 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10173 RSurf_ActiveWorldEntity();
10175 surfaces = model->data_surfaces;
10176 update = model->brushq1.lightmapupdateflags;
10178 // update light styles on this submodel
10179 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
10181 model_brush_lightstyleinfo_t *style;
10182 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10184 if (style->value != r_refdef.scene.lightstylevalue[style->style])
10186 int *list = style->surfacelist;
10187 style->value = r_refdef.scene.lightstylevalue[style->style];
10188 for (j = 0;j < style->numsurfaces;j++)
10189 update[list[j]] = true;
10194 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10198 R_DrawDebugModel();
10199 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10205 rsurface.uselightmaptexture = false;
10206 rsurface.texture = NULL;
10207 rsurface.rtlight = NULL;
10208 numsurfacelist = 0;
10209 // add visible surfaces to draw list
10210 for (i = 0;i < model->nummodelsurfaces;i++)
10212 j = model->sortedmodelsurfaces[i];
10213 if (r_refdef.viewcache.world_surfacevisible[j])
10214 r_surfacelist[numsurfacelist++] = surfaces + j;
10216 // update lightmaps if needed
10220 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10222 if (r_refdef.viewcache.world_surfacevisible[j])
10227 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
10233 int count = model->brushq3.num_mergedlightmaps;
10234 for (i = 0;i < count;i++)
10236 if (model->brushq3.data_deluxemaps[i])
10237 R_FlushTexture(model->brushq3.data_deluxemaps[i]);
10238 if (model->brushq3.data_lightmaps[i])
10239 R_FlushTexture(model->brushq3.data_lightmaps[i]);
10243 // don't do anything if there were no surfaces
10244 if (!numsurfacelist)
10246 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10249 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
10250 GL_AlphaTest(false);
10252 // add to stats if desired
10253 if (r_speeds.integer && !skysurfaces && !depthonly)
10255 r_refdef.stats.world_surfaces += numsurfacelist;
10256 for (j = 0;j < numsurfacelist;j++)
10257 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
10260 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10263 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10265 int i, j, endj, f, flagsmask;
10267 dp_model_t *model = ent->model;
10268 msurface_t *surfaces;
10269 unsigned char *update;
10270 int numsurfacelist = 0;
10274 if (r_maxsurfacelist < model->num_surfaces)
10276 r_maxsurfacelist = model->num_surfaces;
10278 Mem_Free((msurface_t **)r_surfacelist);
10279 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10282 // if the model is static it doesn't matter what value we give for
10283 // wantnormals and wanttangents, so this logic uses only rules applicable
10284 // to a model, knowing that they are meaningless otherwise
10285 if (ent == r_refdef.scene.worldentity)
10286 RSurf_ActiveWorldEntity();
10287 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10288 RSurf_ActiveModelEntity(ent, false, false, false);
10290 RSurf_ActiveModelEntity(ent, true, true, true);
10291 else if (depthonly)
10292 RSurf_ActiveModelEntity(ent, false, false, false);
10295 switch (vid.renderpath)
10297 case RENDERPATH_GL20:
10298 case RENDERPATH_CGGL:
10299 RSurf_ActiveModelEntity(ent, true, true, false);
10301 case RENDERPATH_GL13:
10302 case RENDERPATH_GL11:
10303 RSurf_ActiveModelEntity(ent, true, false, false);
10308 surfaces = model->data_surfaces;
10309 update = model->brushq1.lightmapupdateflags;
10311 // update light styles
10312 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
10314 model_brush_lightstyleinfo_t *style;
10315 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
10317 if (style->value != r_refdef.scene.lightstylevalue[style->style])
10319 int *list = style->surfacelist;
10320 style->value = r_refdef.scene.lightstylevalue[style->style];
10321 for (j = 0;j < style->numsurfaces;j++)
10322 update[list[j]] = true;
10327 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
10331 R_DrawDebugModel();
10332 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10338 rsurface.uselightmaptexture = false;
10339 rsurface.texture = NULL;
10340 rsurface.rtlight = NULL;
10341 numsurfacelist = 0;
10342 // add visible surfaces to draw list
10343 for (i = 0;i < model->nummodelsurfaces;i++)
10344 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
10345 // don't do anything if there were no surfaces
10346 if (!numsurfacelist)
10348 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10351 // update lightmaps if needed
10355 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10360 R_BuildLightMap(ent, surfaces + j);
10365 int count = model->brushq3.num_mergedlightmaps;
10366 for (i = 0;i < count;i++)
10368 if (model->brushq3.data_deluxemaps[i])
10369 R_FlushTexture(model->brushq3.data_deluxemaps[i]);
10370 if (model->brushq3.data_lightmaps[i])
10371 R_FlushTexture(model->brushq3.data_lightmaps[i]);
10376 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
10378 R_BuildLightMap(ent, surfaces + j);
10379 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
10380 GL_AlphaTest(false);
10382 // add to stats if desired
10383 if (r_speeds.integer && !skysurfaces && !depthonly)
10385 r_refdef.stats.entities_surfaces += numsurfacelist;
10386 for (j = 0;j < numsurfacelist;j++)
10387 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
10390 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10393 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
10395 static texture_t texture;
10396 static msurface_t surface;
10397 const msurface_t *surfacelist = &surface;
10399 // fake enough texture and surface state to render this geometry
10401 texture.update_lastrenderframe = -1; // regenerate this texture
10402 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
10403 texture.currentskinframe = skinframe;
10404 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
10405 texture.specularscalemod = 1;
10406 texture.specularpowermod = 1;
10408 surface.texture = &texture;
10409 surface.num_triangles = numtriangles;
10410 surface.num_firsttriangle = firsttriangle;
10411 surface.num_vertices = numvertices;
10412 surface.num_firstvertex = firstvertex;
10415 rsurface.texture = R_GetCurrentTexture(surface.texture);
10416 rsurface.uselightmaptexture = false;
10417 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
10420 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)
10422 static msurface_t surface;
10423 const msurface_t *surfacelist = &surface;
10425 // fake enough texture and surface state to render this geometry
10427 surface.texture = texture;
10428 surface.num_triangles = numtriangles;
10429 surface.num_firsttriangle = firsttriangle;
10430 surface.num_vertices = numvertices;
10431 surface.num_firstvertex = firstvertex;
10434 rsurface.texture = R_GetCurrentTexture(surface.texture);
10435 rsurface.uselightmaptexture = false;
10436 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);