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"
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
32 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 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)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 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"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 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)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
60 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"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
66 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)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 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"};
70 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"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 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"};
73 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"};
74 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"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 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)"};
80 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)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 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."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 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."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 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"};
96 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"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 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"};
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
112 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
113 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
119 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)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 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)"};
125 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)"};
126 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)"};
127 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)"};
129 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)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 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"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 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)"};
153 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"};
155 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"};
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 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"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
166 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
168 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
170 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)"};
172 extern cvar_t v_glslgamma;
174 extern qboolean v_flipped_state;
176 static struct r_bloomstate_s
181 int bloomwidth, bloomheight;
183 int screentexturewidth, screentextureheight;
184 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
186 int bloomtexturewidth, bloomtextureheight;
187 rtexture_t *texture_bloom;
189 // arrays for rendering the screen passes
190 float screentexcoord2f[8];
191 float bloomtexcoord2f[8];
192 float offsettexcoord2f[8];
194 r_viewport_t viewport;
198 r_waterstate_t r_waterstate;
200 /// shadow volume bsp struct with automatically growing nodes buffer
203 rtexture_t *r_texture_blanknormalmap;
204 rtexture_t *r_texture_white;
205 rtexture_t *r_texture_grey128;
206 rtexture_t *r_texture_black;
207 rtexture_t *r_texture_notexture;
208 rtexture_t *r_texture_whitecube;
209 rtexture_t *r_texture_normalizationcube;
210 rtexture_t *r_texture_fogattenuation;
211 rtexture_t *r_texture_gammaramps;
212 unsigned int r_texture_gammaramps_serial;
213 //rtexture_t *r_texture_fogintensity;
215 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
216 unsigned int r_numqueries;
217 unsigned int r_maxqueries;
219 typedef struct r_qwskincache_s
221 char name[MAX_QPATH];
222 skinframe_t *skinframe;
226 static r_qwskincache_t *r_qwskincache;
227 static int r_qwskincache_size;
229 /// vertex coordinates for a quad that covers the screen exactly
230 const float r_screenvertex3f[12] =
238 extern void R_DrawModelShadows(void);
240 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
243 for (i = 0;i < verts;i++)
254 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
257 for (i = 0;i < verts;i++)
267 // FIXME: move this to client?
270 if (gamemode == GAME_NEHAHRA)
272 Cvar_Set("gl_fogenable", "0");
273 Cvar_Set("gl_fogdensity", "0.2");
274 Cvar_Set("gl_fogred", "0.3");
275 Cvar_Set("gl_foggreen", "0.3");
276 Cvar_Set("gl_fogblue", "0.3");
278 r_refdef.fog_density = 0;
279 r_refdef.fog_red = 0;
280 r_refdef.fog_green = 0;
281 r_refdef.fog_blue = 0;
282 r_refdef.fog_alpha = 1;
283 r_refdef.fog_start = 0;
284 r_refdef.fog_end = 16384;
285 r_refdef.fog_height = 1<<30;
286 r_refdef.fog_fadedepth = 128;
289 static void R_BuildBlankTextures(void)
291 unsigned char data[4];
292 data[2] = 128; // normal X
293 data[1] = 128; // normal Y
294 data[0] = 255; // normal Z
295 data[3] = 128; // height
296 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
301 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
306 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
311 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
314 static void R_BuildNoTexture(void)
317 unsigned char pix[16][16][4];
318 // this makes a light grey/dark grey checkerboard texture
319 for (y = 0;y < 16;y++)
321 for (x = 0;x < 16;x++)
323 if ((y < 8) ^ (x < 8))
339 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
342 static void R_BuildWhiteCube(void)
344 unsigned char data[6*1*1*4];
345 memset(data, 255, sizeof(data));
346 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
349 static void R_BuildNormalizationCube(void)
353 vec_t s, t, intensity;
356 data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
357 for (side = 0;side < 6;side++)
359 for (y = 0;y < NORMSIZE;y++)
361 for (x = 0;x < NORMSIZE;x++)
363 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
364 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
399 intensity = 127.0f / sqrt(DotProduct(v, v));
400 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
401 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
402 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
403 data[((side*64+y)*64+x)*4+3] = 255;
407 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
411 static void R_BuildFogTexture(void)
415 unsigned char data1[FOGWIDTH][4];
416 //unsigned char data2[FOGWIDTH][4];
419 r_refdef.fogmasktable_start = r_refdef.fog_start;
420 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
421 r_refdef.fogmasktable_range = r_refdef.fogrange;
422 r_refdef.fogmasktable_density = r_refdef.fog_density;
424 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
425 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
427 d = (x * r - r_refdef.fogmasktable_start);
428 if(developer_extra.integer)
429 Con_DPrintf("%f ", d);
431 if (r_fog_exp2.integer)
432 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
434 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
435 if(developer_extra.integer)
436 Con_DPrintf(" : %f ", alpha);
437 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
438 if(developer_extra.integer)
439 Con_DPrintf(" = %f\n", alpha);
440 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
443 for (x = 0;x < FOGWIDTH;x++)
445 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
450 //data2[x][0] = 255 - b;
451 //data2[x][1] = 255 - b;
452 //data2[x][2] = 255 - b;
455 if (r_texture_fogattenuation)
457 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
458 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
462 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);
463 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
467 //=======================================================================================================================================================
469 static const char *builtinshaderstring =
470 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
471 "// written by Forest 'LordHavoc' Hale\n"
472 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
474 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
477 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
478 "#define USELIGHTMAP\n"
480 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
481 "#define USEEYEVECTOR\n"
484 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
485 "# extension GL_ARB_texture_rectangle : enable\n"
488 "#ifdef USESHADOWMAP2D\n"
489 "# ifdef GL_EXT_gpu_shader4\n"
490 "# extension GL_EXT_gpu_shader4 : enable\n"
492 "# ifdef GL_ARB_texture_gather\n"
493 "# extension GL_ARB_texture_gather : enable\n"
495 "# ifdef GL_AMD_texture_texture4\n"
496 "# extension GL_AMD_texture_texture4 : enable\n"
501 "#ifdef USESHADOWMAPCUBE\n"
502 "# extension GL_EXT_gpu_shader4 : enable\n"
505 "//#ifdef USESHADOWSAMPLER\n"
506 "//# extension GL_ARB_shadow : enable\n"
509 "//#ifdef __GLSL_CG_DATA_TYPES\n"
510 "//# define myhalf half\n"
511 "//# define myhalf2 half2\n"
512 "//# define myhalf3 half3\n"
513 "//# define myhalf4 half4\n"
515 "# define myhalf float\n"
516 "# define myhalf2 vec2\n"
517 "# define myhalf3 vec3\n"
518 "# define myhalf4 vec4\n"
521 "#ifdef VERTEX_SHADER\n"
522 "uniform mat4 ModelViewProjectionMatrix;\n"
525 "#ifdef MODE_DEPTH_OR_SHADOW\n"
526 "#ifdef VERTEX_SHADER\n"
529 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
532 "#else // !MODE_DEPTH_ORSHADOW\n"
537 "#ifdef MODE_SHOWDEPTH\n"
538 "#ifdef VERTEX_SHADER\n"
541 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
542 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
546 "#ifdef FRAGMENT_SHADER\n"
549 " gl_FragColor = gl_Color;\n"
552 "#else // !MODE_SHOWDEPTH\n"
557 "#ifdef MODE_POSTPROCESS\n"
558 "varying vec2 TexCoord1;\n"
559 "varying vec2 TexCoord2;\n"
561 "#ifdef VERTEX_SHADER\n"
564 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
565 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
567 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
572 "#ifdef FRAGMENT_SHADER\n"
573 "uniform sampler2D Texture_First;\n"
575 "uniform sampler2D Texture_Second;\n"
577 "#ifdef USEGAMMARAMPS\n"
578 "uniform sampler2D Texture_GammaRamps;\n"
580 "#ifdef USESATURATION\n"
581 "uniform float Saturation;\n"
583 "#ifdef USEVIEWTINT\n"
584 "uniform vec4 ViewTintColor;\n"
586 "//uncomment these if you want to use them:\n"
587 "uniform vec4 UserVec1;\n"
588 "// uniform vec4 UserVec2;\n"
589 "// uniform vec4 UserVec3;\n"
590 "// uniform vec4 UserVec4;\n"
591 "// uniform float ClientTime;\n"
592 "uniform vec2 PixelSize;\n"
595 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
597 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
599 "#ifdef USEVIEWTINT\n"
600 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
603 "#ifdef USEPOSTPROCESSING\n"
604 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
605 "// 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"
606 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
607 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
608 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
609 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
610 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
611 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
614 "#ifdef USESATURATION\n"
615 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
616 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
617 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
618 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
621 "#ifdef USEGAMMARAMPS\n"
622 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
623 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
624 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
628 "#else // !MODE_POSTPROCESS\n"
633 "#ifdef MODE_GENERIC\n"
634 "#ifdef USEDIFFUSE\n"
635 "varying vec2 TexCoord1;\n"
637 "#ifdef USESPECULAR\n"
638 "varying vec2 TexCoord2;\n"
640 "#ifdef VERTEX_SHADER\n"
643 " gl_FrontColor = gl_Color;\n"
644 "#ifdef USEDIFFUSE\n"
645 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
647 "#ifdef USESPECULAR\n"
648 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
650 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
654 "#ifdef FRAGMENT_SHADER\n"
655 "#ifdef USEDIFFUSE\n"
656 "uniform sampler2D Texture_First;\n"
658 "#ifdef USESPECULAR\n"
659 "uniform sampler2D Texture_Second;\n"
664 " gl_FragColor = gl_Color;\n"
665 "#ifdef USEDIFFUSE\n"
666 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
669 "#ifdef USESPECULAR\n"
670 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
671 "# ifdef USECOLORMAPPING\n"
672 " gl_FragColor *= tex2;\n"
675 " gl_FragColor += tex2;\n"
677 "# ifdef USEVERTEXTEXTUREBLEND\n"
678 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
683 "#else // !MODE_GENERIC\n"
688 "#ifdef MODE_BLOOMBLUR\n"
689 "varying TexCoord;\n"
690 "#ifdef VERTEX_SHADER\n"
693 " gl_FrontColor = gl_Color;\n"
694 " TexCoord = gl_MultiTexCoord0.xy;\n"
695 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
699 "#ifdef FRAGMENT_SHADER\n"
700 "uniform sampler2D Texture_First;\n"
701 "uniform vec4 BloomBlur_Parameters;\n"
706 " vec2 tc = TexCoord;\n"
707 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
708 " tc += BloomBlur_Parameters.xy;\n"
709 " for (i = 1;i < SAMPLES;i++)\n"
711 " color += texture2D(Texture_First, tc).rgb;\n"
712 " tc += BloomBlur_Parameters.xy;\n"
714 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
717 "#else // !MODE_BLOOMBLUR\n"
718 "#ifdef MODE_REFRACTION\n"
719 "varying vec2 TexCoord;\n"
720 "varying vec4 ModelViewProjectionPosition;\n"
721 "uniform mat4 TexMatrix;\n"
722 "#ifdef VERTEX_SHADER\n"
726 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
727 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
728 " ModelViewProjectionPosition = gl_Position;\n"
732 "#ifdef FRAGMENT_SHADER\n"
733 "uniform sampler2D Texture_Normal;\n"
734 "uniform sampler2D Texture_Refraction;\n"
735 "uniform sampler2D Texture_Reflection;\n"
737 "uniform vec4 DistortScaleRefractReflect;\n"
738 "uniform vec4 ScreenScaleRefractReflect;\n"
739 "uniform vec4 ScreenCenterRefractReflect;\n"
740 "uniform vec4 RefractColor;\n"
741 "uniform vec4 ReflectColor;\n"
742 "uniform float ReflectFactor;\n"
743 "uniform float ReflectOffset;\n"
747 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
748 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
749 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
750 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
751 " // FIXME temporary hack to detect the case that the reflection\n"
752 " // gets blackened at edges due to leaving the area that contains actual\n"
754 " // Remove this 'ack once we have a better way to stop this thing from\n"
756 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
757 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
758 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
759 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
760 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
761 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
764 "#else // !MODE_REFRACTION\n"
769 "#ifdef MODE_WATER\n"
770 "varying vec2 TexCoord;\n"
771 "varying vec3 EyeVector;\n"
772 "varying vec4 ModelViewProjectionPosition;\n"
773 "#ifdef VERTEX_SHADER\n"
774 "uniform vec3 EyePosition;\n"
775 "uniform mat4 TexMatrix;\n"
779 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
780 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
781 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
782 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
783 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
784 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
785 " ModelViewProjectionPosition = gl_Position;\n"
789 "#ifdef FRAGMENT_SHADER\n"
790 "uniform sampler2D Texture_Normal;\n"
791 "uniform sampler2D Texture_Refraction;\n"
792 "uniform sampler2D Texture_Reflection;\n"
794 "uniform vec4 DistortScaleRefractReflect;\n"
795 "uniform vec4 ScreenScaleRefractReflect;\n"
796 "uniform vec4 ScreenCenterRefractReflect;\n"
797 "uniform vec4 RefractColor;\n"
798 "uniform vec4 ReflectColor;\n"
799 "uniform float ReflectFactor;\n"
800 "uniform float ReflectOffset;\n"
804 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
805 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
806 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
807 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
808 " // FIXME temporary hack to detect the case that the reflection\n"
809 " // gets blackened at edges due to leaving the area that contains actual\n"
811 " // Remove this 'ack once we have a better way to stop this thing from\n"
813 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
814 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
815 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
816 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
817 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
818 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
819 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
820 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
821 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
822 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
823 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
824 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
827 "#else // !MODE_WATER\n"
832 "// common definitions between vertex shader and fragment shader:\n"
834 "varying vec2 TexCoord;\n"
835 "#ifdef USEVERTEXTEXTUREBLEND\n"
836 "varying vec2 TexCoord2;\n"
838 "#ifdef USELIGHTMAP\n"
839 "varying vec2 TexCoordLightmap;\n"
842 "#ifdef MODE_LIGHTSOURCE\n"
843 "varying vec3 CubeVector;\n"
846 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
847 "varying vec3 LightVector;\n"
850 "#ifdef USEEYEVECTOR\n"
851 "varying vec3 EyeVector;\n"
854 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
858 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
859 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
860 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
863 "#ifdef USEREFLECTION\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
866 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
867 "uniform vec3 LightPosition;\n"
868 "varying vec4 ModelViewPosition;\n"
871 "#ifdef MODE_LIGHTSOURCE\n"
872 "uniform vec3 LightPosition;\n"
874 "uniform vec3 EyePosition;\n"
875 "#ifdef MODE_LIGHTDIRECTION\n"
876 "uniform vec3 LightDir;\n"
878 "uniform vec4 FogPlane;\n"
884 "// 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"
886 "// fragment shader specific:\n"
887 "#ifdef FRAGMENT_SHADER\n"
889 "uniform sampler2D Texture_Normal;\n"
890 "uniform sampler2D Texture_Color;\n"
891 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
892 "uniform sampler2D Texture_Gloss;\n"
895 "uniform sampler2D Texture_Glow;\n"
897 "#ifdef USEVERTEXTEXTUREBLEND\n"
898 "uniform sampler2D Texture_SecondaryNormal;\n"
899 "uniform sampler2D Texture_SecondaryColor;\n"
900 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
901 "uniform sampler2D Texture_SecondaryGloss;\n"
904 "uniform sampler2D Texture_SecondaryGlow;\n"
907 "#ifdef USECOLORMAPPING\n"
908 "uniform sampler2D Texture_Pants;\n"
909 "uniform sampler2D Texture_Shirt;\n"
912 "uniform sampler2D Texture_FogMask;\n"
914 "#ifdef USELIGHTMAP\n"
915 "uniform sampler2D Texture_Lightmap;\n"
917 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
918 "uniform sampler2D Texture_Deluxemap;\n"
920 "#ifdef USEREFLECTION\n"
921 "uniform sampler2D Texture_Reflection;\n"
924 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
925 "uniform sampler2D Texture_ScreenDepth;\n"
926 "uniform sampler2D Texture_ScreenNormalMap;\n"
928 "#ifdef USEDEFERREDLIGHTMAP\n"
929 "uniform sampler2D Texture_ScreenDiffuse;\n"
930 "uniform sampler2D Texture_ScreenSpecular;\n"
933 "uniform myhalf3 Color_Pants;\n"
934 "uniform myhalf3 Color_Shirt;\n"
935 "uniform myhalf3 FogColor;\n"
938 "uniform float FogRangeRecip;\n"
939 "uniform float FogPlaneViewDist;\n"
940 "uniform float FogHeightFade;\n"
941 "float FogVertex(void)\n"
943 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
944 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
946 "#ifdef USEFOGOUTSIDE\n"
947 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
949 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
951 " return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
955 "#ifdef USEOFFSETMAPPING\n"
956 "uniform float OffsetMapping_Scale;\n"
957 "vec2 OffsetMapping(vec2 TexCoord)\n"
959 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
960 " // 14 sample relief mapping: linear search and then binary search\n"
961 " // this basically steps forward a small amount repeatedly until it finds\n"
962 " // itself inside solid, then jitters forward and back using decreasing\n"
963 " // amounts to find the impact\n"
964 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
965 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
966 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
967 " vec3 RT = vec3(TexCoord, 1);\n"
968 " OffsetVector *= 0.1;\n"
969 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
970 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
971 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
972 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
973 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
974 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
975 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
976 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
977 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
978 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
979 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
980 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
981 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
982 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
985 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
986 " // this basically moves forward the full distance, and then backs up based\n"
987 " // on height of samples\n"
988 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
989 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
990 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
991 " TexCoord += OffsetVector;\n"
992 " OffsetVector *= 0.333;\n"
993 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
994 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
995 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
996 " return TexCoord;\n"
999 "#endif // USEOFFSETMAPPING\n"
1001 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1002 "uniform sampler2D Texture_Attenuation;\n"
1003 "uniform samplerCube Texture_Cube;\n"
1005 "#ifdef USESHADOWMAPRECT\n"
1006 "# ifdef USESHADOWSAMPLER\n"
1007 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1009 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1013 "#ifdef USESHADOWMAP2D\n"
1014 "# ifdef USESHADOWSAMPLER\n"
1015 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1017 "uniform sampler2D Texture_ShadowMap2D;\n"
1021 "#ifdef USESHADOWMAPVSDCT\n"
1022 "uniform samplerCube Texture_CubeProjection;\n"
1025 "#ifdef USESHADOWMAPCUBE\n"
1026 "# ifdef USESHADOWSAMPLER\n"
1027 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1029 "uniform samplerCube Texture_ShadowMapCube;\n"
1033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1034 "uniform vec2 ShadowMap_TextureScale;\n"
1035 "uniform vec4 ShadowMap_Parameters;\n"
1038 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1039 "# ifndef USESHADOWMAPVSDCT\n"
1040 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1042 " vec3 adir = abs(dir);\n"
1046 " if (adir.x > adir.y)\n"
1048 " if (adir.x > adir.z) // X\n"
1052 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1058 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1063 " if (adir.y > adir.z) // Y\n"
1067 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1073 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1077 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1078 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1079 " stc.z += ShadowMap_Parameters.z;\n"
1083 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1085 " vec3 adir = abs(dir);\n"
1086 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1087 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1088 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1089 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1090 " stc.z += ShadowMap_Parameters.z;\n"
1094 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1096 "#ifdef USESHADOWMAPCUBE\n"
1097 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1099 " vec3 adir = abs(dir);\n"
1100 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1104 "# ifdef USESHADOWMAPRECT\n"
1105 "float ShadowMapCompare(vec3 dir)\n"
1107 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1109 "# ifdef USESHADOWSAMPLER\n"
1111 "# ifdef USESHADOWMAPPCF\n"
1112 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1113 " 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"
1115 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1120 "# ifdef USESHADOWMAPPCF\n"
1121 "# if USESHADOWMAPPCF > 1\n"
1122 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1123 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1124 " 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"
1125 " 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"
1126 " 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"
1127 " 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"
1128 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1129 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1131 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1132 " vec2 offset = fract(shadowmaptc.xy);\n"
1133 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1134 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1135 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1136 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1137 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1140 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1148 "# ifdef USESHADOWMAP2D\n"
1149 "float ShadowMapCompare(vec3 dir)\n"
1151 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1154 "# ifdef USESHADOWSAMPLER\n"
1155 "# ifdef USESHADOWMAPPCF\n"
1156 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1157 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1158 " 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"
1160 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1163 "# ifdef USESHADOWMAPPCF\n"
1164 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1165 "# ifdef GL_ARB_texture_gather\n"
1166 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1168 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1170 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1171 " center *= ShadowMap_TextureScale;\n"
1172 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1173 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1174 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1175 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1176 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1177 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1178 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1180 "# ifdef GL_EXT_gpu_shader4\n"
1181 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1183 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1185 "# if USESHADOWMAPPCF > 1\n"
1186 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1187 " center *= ShadowMap_TextureScale;\n"
1188 " 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"
1189 " 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"
1190 " 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"
1191 " 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"
1192 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1193 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1195 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1196 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1197 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1198 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1199 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1200 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1204 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1211 "# ifdef USESHADOWMAPCUBE\n"
1212 "float ShadowMapCompare(vec3 dir)\n"
1214 " // apply depth texture cubemap as light filter\n"
1215 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1217 "# ifdef USESHADOWSAMPLER\n"
1218 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1220 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1225 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1226 "#endif // FRAGMENT_SHADER\n"
1231 "#ifdef MODE_DEFERREDGEOMETRY\n"
1232 "#ifdef VERTEX_SHADER\n"
1233 "uniform mat4 TexMatrix;\n"
1234 "#ifdef USEVERTEXTEXTUREBLEND\n"
1235 "uniform mat4 BackgroundTexMatrix;\n"
1237 "uniform mat4 ModelViewMatrix;\n"
1240 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1241 "#ifdef USEVERTEXTEXTUREBLEND\n"
1242 " gl_FrontColor = gl_Color;\n"
1243 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1246 " // transform unnormalized eye direction into tangent space\n"
1247 "#ifdef USEOFFSETMAPPING\n"
1248 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1249 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1250 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1251 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1254 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1255 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1256 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1257 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1259 "#endif // VERTEX_SHADER\n"
1261 "#ifdef FRAGMENT_SHADER\n"
1264 "#ifdef USEOFFSETMAPPING\n"
1265 " // apply offsetmapping\n"
1266 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1267 "#define TexCoord TexCoordOffset\n"
1270 "#ifdef USEALPHAKILL\n"
1271 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1275 "#ifdef USEVERTEXTEXTUREBLEND\n"
1276 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1277 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1278 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1279 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1282 "#ifdef USEVERTEXTEXTUREBLEND\n"
1283 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1285 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1288 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1301 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1304 "#endif // VERTEX_SHADER\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1316 "uniform myhalf2 PixelToScreenTexCoord;\n"
1319 " // calculate viewspace pixel position\n"
1320 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1322 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1323 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1324 " // decode viewspace pixel normal\n"
1325 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1326 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1327 " // surfacenormal = pixel normal in viewspace\n"
1328 " // LightVector = pixel to light in viewspace\n"
1329 " // CubeVector = position in lightspace\n"
1330 " // eyevector = pixel to view in viewspace\n"
1331 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1332 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1333 "#ifdef USEDIFFUSE\n"
1334 " // calculate diffuse shading\n"
1335 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1336 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1338 "#ifdef USESPECULAR\n"
1339 " // calculate directional shading\n"
1340 " vec3 eyevector = position * -1.0;\n"
1341 "# ifdef USEEXACTSPECULARMATH\n"
1342 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1344 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1345 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1349 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1350 " fade *= ShadowMapCompare(CubeVector);\n"
1353 "#ifdef USEDIFFUSE\n"
1354 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1356 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1358 "#ifdef USESPECULAR\n"
1359 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1361 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1364 "# ifdef USECUBEFILTER\n"
1365 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1366 " gl_FragData[0].rgb *= cubecolor;\n"
1367 " gl_FragData[1].rgb *= cubecolor;\n"
1370 "#endif // FRAGMENT_SHADER\n"
1371 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1376 "#ifdef VERTEX_SHADER\n"
1377 "uniform mat4 TexMatrix;\n"
1378 "#ifdef USEVERTEXTEXTUREBLEND\n"
1379 "uniform mat4 BackgroundTexMatrix;\n"
1381 "#ifdef MODE_LIGHTSOURCE\n"
1382 "uniform mat4 ModelToLight;\n"
1386 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1387 " gl_FrontColor = gl_Color;\n"
1389 " // copy the surface texcoord\n"
1390 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1391 "#ifdef USEVERTEXTEXTUREBLEND\n"
1392 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1394 "#ifdef USELIGHTMAP\n"
1395 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1398 "#ifdef MODE_LIGHTSOURCE\n"
1399 " // transform vertex position into light attenuation/cubemap space\n"
1400 " // (-1 to +1 across the light box)\n"
1401 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1403 "# ifdef USEDIFFUSE\n"
1404 " // transform unnormalized light direction into tangent space\n"
1405 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1406 " // normalize it per pixel)\n"
1407 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1408 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1409 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1410 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1414 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1415 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1416 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1417 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1420 " // transform unnormalized eye direction into tangent space\n"
1421 "#ifdef USEEYEVECTOR\n"
1422 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1423 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1424 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1425 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1429 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1430 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1433 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1434 " VectorS = gl_MultiTexCoord1.xyz;\n"
1435 " VectorT = gl_MultiTexCoord2.xyz;\n"
1436 " VectorR = gl_MultiTexCoord3.xyz;\n"
1439 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1440 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1442 "#ifdef USEREFLECTION\n"
1443 " ModelViewProjectionPosition = gl_Position;\n"
1446 "#endif // VERTEX_SHADER\n"
1451 "#ifdef FRAGMENT_SHADER\n"
1452 "#ifdef USEDEFERREDLIGHTMAP\n"
1453 "uniform myhalf2 PixelToScreenTexCoord;\n"
1454 "uniform myhalf3 DeferredMod_Diffuse;\n"
1455 "uniform myhalf3 DeferredMod_Specular;\n"
1457 "uniform myhalf3 Color_Ambient;\n"
1458 "uniform myhalf3 Color_Diffuse;\n"
1459 "uniform myhalf3 Color_Specular;\n"
1460 "uniform myhalf SpecularPower;\n"
1462 "uniform myhalf3 Color_Glow;\n"
1464 "uniform myhalf Alpha;\n"
1465 "#ifdef USEREFLECTION\n"
1466 "uniform vec4 DistortScaleRefractReflect;\n"
1467 "uniform vec4 ScreenScaleRefractReflect;\n"
1468 "uniform vec4 ScreenCenterRefractReflect;\n"
1469 "uniform myhalf4 ReflectColor;\n"
1471 "#ifdef MODE_LIGHTDIRECTION\n"
1472 "uniform myhalf3 LightColor;\n"
1474 "#ifdef MODE_LIGHTSOURCE\n"
1475 "uniform myhalf3 LightColor;\n"
1479 "#ifdef USEOFFSETMAPPING\n"
1480 " // apply offsetmapping\n"
1481 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1482 "#define TexCoord TexCoordOffset\n"
1485 " // combine the diffuse textures (base, pants, shirt)\n"
1486 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1487 "#ifdef USEALPHAKILL\n"
1488 " if (color.a < 0.5)\n"
1491 " color.a *= Alpha;\n"
1492 "#ifdef USECOLORMAPPING\n"
1493 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1495 "#ifdef USEVERTEXTEXTUREBLEND\n"
1496 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1497 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1498 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1499 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1501 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1504 " // get the surface normal\n"
1505 "#ifdef USEVERTEXTEXTUREBLEND\n"
1506 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1508 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1511 " // get the material colors\n"
1512 " myhalf3 diffusetex = color.rgb;\n"
1513 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1514 "# ifdef USEVERTEXTEXTUREBLEND\n"
1515 " myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1517 " myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1524 "#ifdef MODE_LIGHTSOURCE\n"
1525 " // light source\n"
1526 "#ifdef USEDIFFUSE\n"
1527 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1528 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1529 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1530 "#ifdef USESPECULAR\n"
1531 "#ifdef USEEXACTSPECULARMATH\n"
1532 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1534 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1535 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1537 " color.rgb += glosstex * (specular * Color_Specular);\n"
1540 " color.rgb = diffusetex * Color_Ambient;\n"
1542 " color.rgb *= LightColor;\n"
1543 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1544 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1545 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1547 "# ifdef USECUBEFILTER\n"
1548 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1550 "#endif // MODE_LIGHTSOURCE\n"
1555 "#ifdef MODE_LIGHTDIRECTION\n"
1557 "#ifdef USEDIFFUSE\n"
1558 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1560 "#define lightcolor LightColor\n"
1561 "#endif // MODE_LIGHTDIRECTION\n"
1562 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1564 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1565 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1566 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1567 " // convert modelspace light vector to tangentspace\n"
1568 " myhalf3 lightnormal;\n"
1569 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1570 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1571 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1572 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1573 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1574 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1575 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1576 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1577 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1578 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1579 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1580 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1581 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1582 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1583 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1585 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1586 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1587 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1593 "#ifdef MODE_LIGHTMAP\n"
1594 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1595 "#endif // MODE_LIGHTMAP\n"
1596 "#ifdef MODE_VERTEXCOLOR\n"
1597 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1598 "#endif // MODE_VERTEXCOLOR\n"
1599 "#ifdef MODE_FLATCOLOR\n"
1600 " color.rgb = diffusetex * Color_Ambient;\n"
1601 "#endif // MODE_FLATCOLOR\n"
1607 "# ifdef USEDIFFUSE\n"
1608 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1609 "# ifdef USESPECULAR\n"
1610 "# ifdef USEEXACTSPECULARMATH\n"
1611 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1613 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1614 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1616 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1618 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1621 " color.rgb = diffusetex * Color_Ambient;\n"
1625 "#ifdef USEDEFERREDLIGHTMAP\n"
1626 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1627 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1628 " color.rgb += glosstex * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1632 "#ifdef USEVERTEXTEXTUREBLEND\n"
1633 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1635 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1640 "#ifdef MODE_LIGHTSOURCE\n"
1641 " color.rgb *= myhalf(FogVertex());\n"
1643 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1647 " // 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"
1648 "#ifdef USEREFLECTION\n"
1649 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1650 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1651 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1652 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1653 " // FIXME temporary hack to detect the case that the reflection\n"
1654 " // gets blackened at edges due to leaving the area that contains actual\n"
1656 " // Remove this 'ack once we have a better way to stop this thing from\n"
1658 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1659 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1660 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1661 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1662 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1663 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1666 " gl_FragColor = vec4(color);\n"
1668 "#endif // FRAGMENT_SHADER\n"
1670 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1671 "#endif // !MODE_DEFERREDGEOMETRY\n"
1672 "#endif // !MODE_WATER\n"
1673 "#endif // !MODE_REFRACTION\n"
1674 "#endif // !MODE_BLOOMBLUR\n"
1675 "#endif // !MODE_GENERIC\n"
1676 "#endif // !MODE_POSTPROCESS\n"
1677 "#endif // !MODE_SHOWDEPTH\n"
1678 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1682 =========================================================================================================================================================
1686 =========================================================================================================================================================
1690 =========================================================================================================================================================
1694 =========================================================================================================================================================
1698 =========================================================================================================================================================
1702 =========================================================================================================================================================
1706 =========================================================================================================================================================
1709 const char *builtincgshaderstring =
1710 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1711 "// written by Forest 'LordHavoc' Hale\n"
1712 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1714 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1717 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1718 "#define USELIGHTMAP\n"
1720 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1721 "#define USEEYEVECTOR\n"
1724 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1725 "#ifdef VERTEX_SHADER\n"
1728 "float4 gl_Vertex : POSITION,\n"
1729 "uniform float4x4 ModelViewProjectionMatrix,\n"
1730 "out float4 gl_Position : POSITION\n"
1733 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1736 "#else // !MODE_DEPTH_ORSHADOW\n"
1741 "#ifdef MODE_SHOWDEPTH\n"
1742 "#ifdef VERTEX_SHADER\n"
1745 "float4 gl_Vertex : POSITION,\n"
1746 "uniform float4x4 ModelViewProjectionMatrix,\n"
1747 "out float4 gl_Position : POSITION,\n"
1748 "out float4 gl_FrontColor : COLOR0\n"
1751 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1752 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1756 "#ifdef FRAGMENT_SHADER\n"
1759 "float4 gl_FrontColor : COLOR0,\n"
1760 "out float4 gl_FragColor : COLOR\n"
1763 " gl_FragColor = gl_FrontColor;\n"
1766 "#else // !MODE_SHOWDEPTH\n"
1771 "#ifdef MODE_POSTPROCESS\n"
1773 "#ifdef VERTEX_SHADER\n"
1776 "float4 gl_Vertex : POSITION,\n"
1777 "uniform float4x4 ModelViewProjectionMatrix,\n"
1778 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1779 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1780 "out float4 gl_Position : POSITION,\n"
1781 "out float2 TexCoord1 : TEXCOORD0,\n"
1782 "out float2 TexCoord2 : TEXCOORD1\n"
1785 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1786 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1788 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1793 "#ifdef FRAGMENT_SHADER\n"
1796 "float2 TexCoord1 : TEXCOORD0,\n"
1797 "float2 TexCoord2 : TEXCOORD1,\n"
1798 "uniform sampler2D Texture_First,\n"
1800 "uniform sampler2D Texture_Second,\n"
1802 "#ifdef USEGAMMARAMPS\n"
1803 "uniform sampler2D Texture_GammaRamps,\n"
1805 "#ifdef USESATURATION\n"
1806 "uniform float Saturation,\n"
1808 "#ifdef USEVIEWTINT\n"
1809 "uniform float4 ViewTintColor,\n"
1811 "uniform float4 UserVec1,\n"
1812 "uniform float4 UserVec2,\n"
1813 "uniform float4 UserVec3,\n"
1814 "uniform float4 UserVec4,\n"
1815 "uniform float ClientTime,\n"
1816 "uniform float2 PixelSize,\n"
1817 "out float4 gl_FragColor : COLOR\n"
1820 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1822 " gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1824 "#ifdef USEVIEWTINT\n"
1825 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1828 "#ifdef USEPOSTPROCESSING\n"
1829 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1830 "// 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"
1831 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1832 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1833 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1834 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1835 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1836 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1839 "#ifdef USESATURATION\n"
1840 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1841 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1842 " //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1843 " gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1846 "#ifdef USEGAMMARAMPS\n"
1847 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1848 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1849 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1853 "#else // !MODE_POSTPROCESS\n"
1858 "#ifdef MODE_GENERIC\n"
1859 "#ifdef VERTEX_SHADER\n"
1862 "float4 gl_Vertex : POSITION,\n"
1863 "uniform float4x4 ModelViewProjectionMatrix,\n"
1864 "float4 gl_Color : COLOR0,\n"
1865 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1866 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1867 "out float4 gl_Position : POSITION,\n"
1868 "out float4 gl_FrontColor : COLOR,\n"
1869 "out float2 TexCoord1 : TEXCOORD0,\n"
1870 "out float2 TexCoord2 : TEXCOORD1\n"
1873 " gl_FrontColor = gl_Color;\n"
1874 "#ifdef USEDIFFUSE\n"
1875 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1877 "#ifdef USESPECULAR\n"
1878 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1880 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1884 "#ifdef FRAGMENT_SHADER\n"
1888 "float4 gl_FrontColor : COLOR,\n"
1889 "float2 TexCoord1 : TEXCOORD0,\n"
1890 "float2 TexCoord2 : TEXCOORD1,\n"
1891 "#ifdef USEDIFFUSE\n"
1892 "uniform sampler2D Texture_First,\n"
1894 "#ifdef USESPECULAR\n"
1895 "uniform sampler2D Texture_Second,\n"
1897 "out float4 gl_FragColor : COLOR\n"
1900 " gl_FragColor = gl_FrontColor;\n"
1901 "#ifdef USEDIFFUSE\n"
1902 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1905 "#ifdef USESPECULAR\n"
1906 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1907 "# ifdef USECOLORMAPPING\n"
1908 " gl_FragColor *= tex2;\n"
1911 " gl_FragColor += tex2;\n"
1913 "# ifdef USEVERTEXTEXTUREBLEND\n"
1914 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1919 "#else // !MODE_GENERIC\n"
1924 "#ifdef MODE_BLOOMBLUR\n"
1925 "#ifdef VERTEX_SHADER\n"
1928 "float4 gl_Vertex : POSITION,\n"
1929 "uniform float4x4 ModelViewProjectionMatrix,\n"
1930 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1931 "out float4 gl_Position : POSITION,\n"
1932 "out float2 TexCoord : TEXCOORD0\n"
1935 " TexCoord = gl_MultiTexCoord0.xy;\n"
1936 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1940 "#ifdef FRAGMENT_SHADER\n"
1944 "float2 TexCoord : TEXCOORD0,\n"
1945 "uniform sampler2D Texture_First,\n"
1946 "uniform float4 BloomBlur_Parameters,\n"
1947 "out float4 gl_FragColor : COLOR\n"
1951 " float2 tc = TexCoord;\n"
1952 " float3 color = tex2D(Texture_First, tc).rgb;\n"
1953 " tc += BloomBlur_Parameters.xy;\n"
1954 " for (i = 1;i < SAMPLES;i++)\n"
1956 " color += tex2D(Texture_First, tc).rgb;\n"
1957 " tc += BloomBlur_Parameters.xy;\n"
1959 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1962 "#else // !MODE_BLOOMBLUR\n"
1963 "#ifdef MODE_REFRACTION\n"
1964 "#ifdef VERTEX_SHADER\n"
1967 "float4 gl_Vertex : POSITION,\n"
1968 "uniform float4x4 ModelViewProjectionMatrix,\n"
1969 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1970 "uniform float4x4 TexMatrix,\n"
1971 "uniform float3 EyePosition,\n"
1972 "out float4 gl_Position : POSITION,\n"
1973 "out float2 TexCoord : TEXCOORD0,\n"
1974 "out float3 EyeVector : TEXCOORD1,\n"
1975 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1978 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1979 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1980 " ModelViewProjectionPosition = gl_Position;\n"
1984 "#ifdef FRAGMENT_SHADER\n"
1987 "float2 TexCoord : TEXCOORD0,\n"
1988 "float3 EyeVector : TEXCOORD1,\n"
1989 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1990 "uniform sampler2D Texture_Normal,\n"
1991 "uniform sampler2D Texture_Refraction,\n"
1992 "uniform sampler2D Texture_Reflection,\n"
1993 "uniform float4 DistortScaleRefractReflect,\n"
1994 "uniform float4 ScreenScaleRefractReflect,\n"
1995 "uniform float4 ScreenCenterRefractReflect,\n"
1996 "uniform float4 RefractColor,\n"
1997 "out float4 gl_FragColor : COLOR\n"
2000 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2001 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2002 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2003 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2004 " // FIXME temporary hack to detect the case that the reflection\n"
2005 " // gets blackened at edges due to leaving the area that contains actual\n"
2007 " // Remove this 'ack once we have a better way to stop this thing from\n"
2009 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2010 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2011 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2012 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2013 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2014 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2017 "#else // !MODE_REFRACTION\n"
2022 "#ifdef MODE_WATER\n"
2023 "#ifdef VERTEX_SHADER\n"
2027 "float4 gl_Vertex : POSITION,\n"
2028 "uniform float4x4 ModelViewProjectionMatrix,\n"
2029 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2030 "uniform float4x4 TexMatrix,\n"
2031 "uniform float3 EyePosition,\n"
2032 "out float4 gl_Position : POSITION,\n"
2033 "out float2 TexCoord : TEXCOORD0,\n"
2034 "out float3 EyeVector : TEXCOORD1,\n"
2035 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2038 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2039 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2040 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2041 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2042 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2043 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2044 " ModelViewProjectionPosition = gl_Position;\n"
2048 "#ifdef FRAGMENT_SHADER\n"
2051 "float2 TexCoord : TEXCOORD0,\n"
2052 "float3 EyeVector : TEXCOORD1,\n"
2053 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2054 "uniform sampler2D Texture_Normal,\n"
2055 "uniform sampler2D Texture_Refraction,\n"
2056 "uniform sampler2D Texture_Reflection,\n"
2057 "uniform float4 DistortScaleRefractReflect,\n"
2058 "uniform float4 ScreenScaleRefractReflect,\n"
2059 "uniform float4 ScreenCenterRefractReflect,\n"
2060 "uniform float4 RefractColor,\n"
2061 "uniform float4 ReflectColor,\n"
2062 "uniform float ReflectFactor,\n"
2063 "uniform float ReflectOffset,\n"
2064 "out float4 gl_FragColor : COLOR\n"
2067 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2068 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2069 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2070 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2071 " // FIXME temporary hack to detect the case that the reflection\n"
2072 " // gets blackened at edges due to leaving the area that contains actual\n"
2074 " // Remove this 'ack once we have a better way to stop this thing from\n"
2076 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2077 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2078 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2079 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2080 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2081 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2082 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2083 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2084 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2085 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2086 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2087 " gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2090 "#else // !MODE_WATER\n"
2095 "// 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"
2097 "// fragment shader specific:\n"
2098 "#ifdef FRAGMENT_SHADER\n"
2101 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2104 "#ifdef USEFOGOUTSIDE\n"
2105 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2107 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2109 " return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2113 "#ifdef USEOFFSETMAPPING\n"
2114 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2116 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2117 " // 14 sample relief mapping: linear search and then binary search\n"
2118 " // this basically steps forward a small amount repeatedly until it finds\n"
2119 " // itself inside solid, then jitters forward and back using decreasing\n"
2120 " // amounts to find the impact\n"
2121 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2122 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2123 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2124 " float3 RT = float3(TexCoord, 1);\n"
2125 " OffsetVector *= 0.1;\n"
2126 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2127 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2128 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2129 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2130 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2131 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2132 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2133 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2134 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2135 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2136 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2137 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2138 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2139 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2142 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2143 " // this basically moves forward the full distance, and then backs up based\n"
2144 " // on height of samples\n"
2145 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2146 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2147 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2148 " TexCoord += OffsetVector;\n"
2149 " OffsetVector *= 0.333;\n"
2150 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2151 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2152 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2153 " return TexCoord;\n"
2156 "#endif // USEOFFSETMAPPING\n"
2158 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2159 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2160 "# ifndef USESHADOWMAPVSDCT\n"
2161 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2163 " float3 adir = abs(dir);\n"
2167 " if (adir.x > adir.y)\n"
2169 " if (adir.x > adir.z) // X\n"
2173 " offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2179 " offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2184 " if (adir.y > adir.z) // Y\n"
2188 " offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2194 " offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2198 " float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2199 " stc.xy += offset * ShadowMap_Parameters.y;\n"
2200 " stc.z += ShadowMap_Parameters.z;\n"
2204 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2206 " float3 adir = abs(dir);\n"
2207 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2208 " float ma = max(max(adir.x, adir.y), adir.z);\n"
2209 " float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2210 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2211 " stc.z += ShadowMap_Parameters.z;\n"
2215 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2217 "#ifdef USESHADOWMAPCUBE\n"
2218 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2220 " float3 adir = abs(dir);\n"
2221 " return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2225 "# ifdef USESHADOWMAPRECT\n"
2226 "#ifdef USESHADOWMAPVSDCT\n"
2227 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2229 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2232 "#ifdef USESHADOWMAPVSDCT\n"
2233 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2235 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2238 "# ifdef USESHADOWSAMPLER\n"
2240 "# ifdef USESHADOWMAPPCF\n"
2241 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2242 " f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2244 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2249 "# ifdef USESHADOWMAPPCF\n"
2250 "# if USESHADOWMAPPCF > 1\n"
2251 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2252 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2253 " float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2254 " float4 row2 = step(shadowmaptc.z, float4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
2255 " float4 row3 = step(shadowmaptc.z, float4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
2256 " float4 row4 = step(shadowmaptc.z, float4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
2257 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2258 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2260 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2261 " float2 offset = frac(shadowmaptc.xy);\n"
2262 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2263 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2264 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2265 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2266 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2269 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2277 "# ifdef USESHADOWMAP2D\n"
2278 "#ifdef USESHADOWMAPVSDCT\n"
2279 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2281 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2284 "#ifdef USESHADOWMAPVSDCT\n"
2285 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2287 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2291 "# ifdef USESHADOWSAMPLER\n"
2292 "# ifdef USESHADOWMAPPCF\n"
2293 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
2294 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2295 " f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2297 " f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2300 "# ifdef USESHADOWMAPPCF\n"
2301 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2302 "# ifdef GL_ARB_texture_gather\n"
2303 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2305 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2307 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2308 " center *= ShadowMap_TextureScale;\n"
2309 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2310 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2311 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2312 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2313 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2314 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2315 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2317 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale) \n"
2318 "# if USESHADOWMAPPCF > 1\n"
2319 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2320 " center *= ShadowMap_TextureScale;\n"
2321 " float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2322 " float4 row2 = step(shadowmaptc.z, float4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
2323 " float4 row3 = step(shadowmaptc.z, float4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
2324 " float4 row4 = step(shadowmaptc.z, float4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
2325 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2326 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2328 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2329 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2330 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2331 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2332 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2333 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2337 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2344 "# ifdef USESHADOWMAPCUBE\n"
2345 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2347 " // apply depth texture cubemap as light filter\n"
2348 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2350 "# ifdef USESHADOWSAMPLER\n"
2351 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2353 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2358 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2359 "#endif // FRAGMENT_SHADER\n"
2364 "#ifdef MODE_DEFERREDGEOMETRY\n"
2365 "#ifdef VERTEX_SHADER\n"
2368 "float4 gl_Vertex : POSITION,\n"
2369 "uniform float4x4 ModelViewProjectionMatrix,\n"
2370 "#ifdef USEVERTEXTEXTUREBLEND\n"
2371 "float4 gl_Color : COLOR0,\n"
2373 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2374 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2375 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2376 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2377 "uniform float4x4 TexMatrix,\n"
2378 "#ifdef USEVERTEXTEXTUREBLEND\n"
2379 "uniform float4x4 BackgroundTexMatrix,\n"
2381 "uniform float4x4 ModelViewMatrix,\n"
2382 "#ifdef USEOFFSETMAPPING\n"
2383 "uniform float3 EyePosition,\n"
2385 "out float4 gl_Position : POSITION,\n"
2386 "out float4 gl_FrontColor : COLOR,\n"
2387 "out float4 TexCoordBoth : TEXCOORD0,\n"
2388 "#ifdef USEOFFSETMAPPING\n"
2389 "out float3 EyeVector : TEXCOORD2,\n"
2391 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2392 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2393 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2396 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2397 "#ifdef USEVERTEXTEXTUREBLEND\n"
2398 " gl_FrontColor = gl_Color;\n"
2399 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2402 " // transform unnormalized eye direction into tangent space\n"
2403 "#ifdef USEOFFSETMAPPING\n"
2404 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2405 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2406 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2407 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2410 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2411 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2412 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2413 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2415 "#endif // VERTEX_SHADER\n"
2417 "#ifdef FRAGMENT_SHADER\n"
2420 "float4 TexCoordBoth : TEXCOORD0,\n"
2421 "float3 EyeVector : TEXCOORD2,\n"
2422 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2423 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2424 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2425 "uniform sampler2D Texture_Normal,\n"
2426 "#ifdef USEALPHAKILL\n"
2427 "uniform sampler2D Texture_Color,\n"
2429 "#ifdef USEVERTEXTEXTUREBLEND\n"
2430 "uniform sampler2D Texture_SecondaryNormal,\n"
2432 "#ifdef USEOFFSETMAPPING\n"
2433 "uniform float OffsetMapping_Scale,\n"
2435 "uniform half SpecularPower,\n"
2436 "out float4 gl_FragColor : COLOR\n"
2439 " float2 TexCoord = TexCoordBoth.xy;\n"
2440 "#ifdef USEOFFSETMAPPING\n"
2441 " // apply offsetmapping\n"
2442 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2443 "#define TexCoord TexCoordOffset\n"
2446 "#ifdef USEALPHAKILL\n"
2447 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2451 "#ifdef USEVERTEXTEXTUREBLEND\n"
2452 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2453 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2454 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2455 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2458 "#ifdef USEVERTEXTEXTUREBLEND\n"
2459 " float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2461 " float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2464 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2466 "#endif // FRAGMENT_SHADER\n"
2467 "#else // !MODE_DEFERREDGEOMETRY\n"
2472 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2473 "#ifdef VERTEX_SHADER\n"
2476 "float4 gl_Vertex : POSITION,\n"
2477 "uniform float4x4 ModelViewProjectionMatrix,\n"
2478 "uniform float4x4 ModelViewMatrix,\n"
2479 "out float4 gl_Position : POSITION,\n"
2480 "out float4 ModelViewPosition : TEXCOORD0\n"
2483 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2484 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2486 "#endif // VERTEX_SHADER\n"
2488 "#ifdef FRAGMENT_SHADER\n"
2491 "float2 Pixel : WPOS,\n"
2492 "float4 ModelViewPosition : TEXCOORD0,\n"
2493 "uniform float4x4 ViewToLight,\n"
2494 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2495 "uniform float3 LightPosition,\n"
2496 "uniform half2 PixelToScreenTexCoord,\n"
2497 "uniform half3 DeferredColor_Ambient,\n"
2498 "uniform half3 DeferredColor_Diffuse,\n"
2499 "#ifdef USESPECULAR\n"
2500 "uniform half3 DeferredColor_Specular,\n"
2501 "uniform half SpecularPower,\n"
2503 "uniform sampler2D Texture_Attenuation,\n"
2504 "uniform sampler2D Texture_ScreenDepth,\n"
2505 "uniform sampler2D Texture_ScreenNormalMap,\n"
2507 "#ifdef USESHADOWMAPRECT\n"
2508 "# ifdef USESHADOWSAMPLER\n"
2509 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2511 "uniform samplerRECT Texture_ShadowMapRect,\n"
2515 "#ifdef USESHADOWMAP2D\n"
2516 "# ifdef USESHADOWSAMPLER\n"
2517 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2519 "uniform sampler2D Texture_ShadowMap2D,\n"
2523 "#ifdef USESHADOWMAPVSDCT\n"
2524 "uniform samplerCUBE Texture_CubeProjection,\n"
2527 "#ifdef USESHADOWMAPCUBE\n"
2528 "# ifdef USESHADOWSAMPLER\n"
2529 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2531 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2535 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2536 "uniform float2 ShadowMap_TextureScale,\n"
2537 "uniform float4 ShadowMap_Parameters,\n"
2540 "out float4 gl_FragData0 : COLOR0,\n"
2541 "out float4 gl_FragData1 : COLOR1\n"
2544 " // calculate viewspace pixel position\n"
2545 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2546 " ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2547 " float3 position;\n"
2548 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2549 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2550 " // decode viewspace pixel normal\n"
2551 " half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2552 " half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2553 " // surfacenormal = pixel normal in viewspace\n"
2554 " // LightVector = pixel to light in viewspace\n"
2555 " // CubeVector = position in lightspace\n"
2556 " // eyevector = pixel to view in viewspace\n"
2557 " float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2558 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2559 "#ifdef USEDIFFUSE\n"
2560 " // calculate diffuse shading\n"
2561 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2562 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2564 "#ifdef USESPECULAR\n"
2565 " // calculate directional shading\n"
2566 " float3 eyevector = position * -1.0;\n"
2567 "# ifdef USEEXACTSPECULARMATH\n"
2568 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2570 " half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2571 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2575 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2576 " fade *= ShadowMapCompare(CubeVector,\n"
2577 "# if defined(USESHADOWMAP2D)\n"
2578 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2580 "# if defined(USESHADOWMAPRECT)\n"
2581 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2583 "# if defined(USESHADOWMAPCUBE)\n"
2584 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2587 "#ifdef USESHADOWMAPVSDCT\n"
2588 ", Texture_CubeProjection\n"
2593 "#ifdef USEDIFFUSE\n"
2594 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2596 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2598 "#ifdef USESPECULAR\n"
2599 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2601 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2604 "# ifdef USECUBEFILTER\n"
2605 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2606 " gl_FragData0.rgb *= cubecolor;\n"
2607 " gl_FragData1.rgb *= cubecolor;\n"
2610 "#endif // FRAGMENT_SHADER\n"
2611 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2616 "#ifdef VERTEX_SHADER\n"
2619 "float4 gl_Vertex : POSITION,\n"
2620 "uniform float4x4 ModelViewProjectionMatrix,\n"
2621 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2622 "float4 gl_Color : COLOR0,\n"
2624 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2625 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2626 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2627 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2628 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2630 "uniform float3 EyePosition,\n"
2631 "uniform float4x4 TexMatrix,\n"
2632 "#ifdef USEVERTEXTEXTUREBLEND\n"
2633 "uniform float4x4 BackgroundTexMatrix,\n"
2635 "#ifdef MODE_LIGHTSOURCE\n"
2636 "uniform float4x4 ModelToLight,\n"
2638 "#ifdef MODE_LIGHTSOURCE\n"
2639 "uniform float3 LightPosition,\n"
2641 "#ifdef MODE_LIGHTDIRECTION\n"
2642 "uniform float3 LightDir,\n"
2644 "uniform float4 FogPlane,\n"
2645 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2646 "uniform float3 LightPosition,\n"
2649 "out float4 gl_FrontColor : COLOR,\n"
2650 "out float4 TexCoordBoth : TEXCOORD0,\n"
2651 "#ifdef USELIGHTMAP\n"
2652 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2654 "#ifdef USEEYEVECTOR\n"
2655 "out float3 EyeVector : TEXCOORD2,\n"
2657 "#ifdef USEREFLECTION\n"
2658 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2661 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2663 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2664 "out float3 LightVector : TEXCOORD5,\n"
2666 "#ifdef MODE_LIGHTSOURCE\n"
2667 "out float3 CubeVector : TEXCOORD3,\n"
2669 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2670 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2671 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2672 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2674 "out float4 gl_Position : POSITION\n"
2677 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2678 " gl_FrontColor = gl_Color;\n"
2680 " // copy the surface texcoord\n"
2681 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2682 "#ifdef USEVERTEXTEXTUREBLEND\n"
2683 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2685 "#ifdef USELIGHTMAP\n"
2686 " TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2689 "#ifdef MODE_LIGHTSOURCE\n"
2690 " // transform vertex position into light attenuation/cubemap space\n"
2691 " // (-1 to +1 across the light box)\n"
2692 " CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2694 "# ifdef USEDIFFUSE\n"
2695 " // transform unnormalized light direction into tangent space\n"
2696 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2697 " // normalize it per pixel)\n"
2698 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2699 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2700 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2701 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2705 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2706 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2707 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2708 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2711 " // transform unnormalized eye direction into tangent space\n"
2712 "#ifdef USEEYEVECTOR\n"
2713 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2714 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2715 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2716 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2720 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2721 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2724 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2725 " VectorS = gl_MultiTexCoord1.xyz;\n"
2726 " VectorT = gl_MultiTexCoord2.xyz;\n"
2727 " VectorR = gl_MultiTexCoord3.xyz;\n"
2730 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2731 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2733 "#ifdef USEREFLECTION\n"
2734 " ModelViewProjectionPosition = gl_Position;\n"
2737 "#endif // VERTEX_SHADER\n"
2742 "#ifdef FRAGMENT_SHADER\n"
2745 "#ifdef USEDEFERREDLIGHTMAP\n"
2746 "float2 Pixel : WPOS,\n"
2748 "float4 gl_FrontColor : COLOR,\n"
2749 "float4 TexCoordBoth : TEXCOORD0,\n"
2750 "#ifdef USELIGHTMAP\n"
2751 "float2 TexCoordLightmap : TEXCOORD1,\n"
2753 "#ifdef USEEYEVECTOR\n"
2754 "float3 EyeVector : TEXCOORD2,\n"
2756 "#ifdef USEREFLECTION\n"
2757 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2760 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2762 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2763 "float3 LightVector : TEXCOORD5,\n"
2765 "#ifdef MODE_LIGHTSOURCE\n"
2766 "float3 CubeVector : TEXCOORD3,\n"
2768 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2769 "float4 ModelViewPosition : TEXCOORD0,\n"
2771 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2772 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2773 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2774 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2777 "uniform sampler2D Texture_Normal,\n"
2778 "uniform sampler2D Texture_Color,\n"
2779 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2780 "uniform sampler2D Texture_Gloss,\n"
2783 "uniform sampler2D Texture_Glow,\n"
2785 "#ifdef USEVERTEXTEXTUREBLEND\n"
2786 "uniform sampler2D Texture_SecondaryNormal,\n"
2787 "uniform sampler2D Texture_SecondaryColor,\n"
2788 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2789 "uniform sampler2D Texture_SecondaryGloss,\n"
2792 "uniform sampler2D Texture_SecondaryGlow,\n"
2795 "#ifdef USECOLORMAPPING\n"
2796 "uniform sampler2D Texture_Pants,\n"
2797 "uniform sampler2D Texture_Shirt,\n"
2800 "uniform sampler2D Texture_FogMask,\n"
2802 "#ifdef USELIGHTMAP\n"
2803 "uniform sampler2D Texture_Lightmap,\n"
2805 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2806 "uniform sampler2D Texture_Deluxemap,\n"
2808 "#ifdef USEREFLECTION\n"
2809 "uniform sampler2D Texture_Reflection,\n"
2812 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2813 "uniform sampler2D Texture_ScreenDepth,\n"
2814 "uniform sampler2D Texture_ScreenNormalMap,\n"
2816 "#ifdef USEDEFERREDLIGHTMAP\n"
2817 "uniform sampler2D Texture_ScreenDiffuse,\n"
2818 "uniform sampler2D Texture_ScreenSpecular,\n"
2821 "#ifdef USECOLORMAPPING\n"
2822 "uniform half3 Color_Pants,\n"
2823 "uniform half3 Color_Shirt,\n"
2826 "uniform float3 FogColor,\n"
2827 "uniform float FogRangeRecip,\n"
2828 "uniform float FogPlaneViewDist,\n"
2829 "uniform float FogHeightFade,\n"
2832 "#ifdef USEOFFSETMAPPING\n"
2833 "uniform float OffsetMapping_Scale,\n"
2836 "#ifdef USEDEFERREDLIGHTMAP\n"
2837 "uniform half2 PixelToScreenTexCoord,\n"
2838 "uniform half3 DeferredMod_Diffuse,\n"
2839 "uniform half3 DeferredMod_Specular,\n"
2841 "uniform half3 Color_Ambient,\n"
2842 "uniform half3 Color_Diffuse,\n"
2843 "uniform half3 Color_Specular,\n"
2844 "uniform half SpecularPower,\n"
2846 "uniform half3 Color_Glow,\n"
2848 "uniform half Alpha,\n"
2849 "#ifdef USEREFLECTION\n"
2850 "uniform float4 DistortScaleRefractReflect,\n"
2851 "uniform float4 ScreenScaleRefractReflect,\n"
2852 "uniform float4 ScreenCenterRefractReflect,\n"
2853 "uniform half4 ReflectColor,\n"
2855 "#ifdef MODE_LIGHTDIRECTION\n"
2856 "uniform half3 LightColor,\n"
2858 "#ifdef MODE_LIGHTSOURCE\n"
2859 "uniform half3 LightColor,\n"
2862 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2863 "uniform sampler2D Texture_Attenuation,\n"
2864 "uniform samplerCUBE Texture_Cube,\n"
2866 "#ifdef USESHADOWMAPRECT\n"
2867 "# ifdef USESHADOWSAMPLER\n"
2868 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2870 "uniform samplerRECT Texture_ShadowMapRect,\n"
2874 "#ifdef USESHADOWMAP2D\n"
2875 "# ifdef USESHADOWSAMPLER\n"
2876 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2878 "uniform sampler2D Texture_ShadowMap2D,\n"
2882 "#ifdef USESHADOWMAPVSDCT\n"
2883 "uniform samplerCUBE Texture_CubeProjection,\n"
2886 "#ifdef USESHADOWMAPCUBE\n"
2887 "# ifdef USESHADOWSAMPLER\n"
2888 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2890 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2894 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2895 "uniform float2 ShadowMap_TextureScale,\n"
2896 "uniform float4 ShadowMap_Parameters,\n"
2898 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2900 "out float4 gl_FragColor : COLOR\n"
2903 " float2 TexCoord = TexCoordBoth.xy;\n"
2904 "#ifdef USEVERTEXTEXTUREBLEND\n"
2905 " float2 TexCoord2 = TexCoordBoth.zw;\n"
2907 "#ifdef USEOFFSETMAPPING\n"
2908 " // apply offsetmapping\n"
2909 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2910 "#define TexCoord TexCoordOffset\n"
2913 " // combine the diffuse textures (base, pants, shirt)\n"
2914 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2915 "#ifdef USEALPHAKILL\n"
2916 " if (color.a < 0.5)\n"
2919 " color.a *= Alpha;\n"
2920 "#ifdef USECOLORMAPPING\n"
2921 " color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2923 "#ifdef USEVERTEXTEXTUREBLEND\n"
2924 " float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2925 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2926 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2927 " color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2929 " //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2932 " // get the surface normal\n"
2933 "#ifdef USEVERTEXTEXTUREBLEND\n"
2934 " half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2936 " half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2939 " // get the material colors\n"
2940 " half3 diffusetex = color.rgb;\n"
2941 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2942 "# ifdef USEVERTEXTEXTUREBLEND\n"
2943 " half3 glosstex = half3(lerp(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2945 " half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2952 "#ifdef MODE_LIGHTSOURCE\n"
2953 " // light source\n"
2954 "#ifdef USEDIFFUSE\n"
2955 " half3 lightnormal = half3(normalize(LightVector));\n"
2956 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2957 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2958 "#ifdef USESPECULAR\n"
2959 "#ifdef USEEXACTSPECULARMATH\n"
2960 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2962 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2963 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2965 " color.rgb += glosstex * (specular * Color_Specular);\n"
2968 " color.rgb = diffusetex * Color_Ambient;\n"
2970 " color.rgb *= LightColor;\n"
2971 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2972 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2973 " color.rgb *= ShadowMapCompare(CubeVector,\n"
2974 "# if defined(USESHADOWMAP2D)\n"
2975 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2977 "# if defined(USESHADOWMAPRECT)\n"
2978 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2980 "# if defined(USESHADOWMAPCUBE)\n"
2981 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2984 "#ifdef USESHADOWMAPVSDCT\n"
2985 ", Texture_CubeProjection\n"
2990 "# ifdef USECUBEFILTER\n"
2991 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2993 "#endif // MODE_LIGHTSOURCE\n"
2998 "#ifdef MODE_LIGHTDIRECTION\n"
3000 "#ifdef USEDIFFUSE\n"
3001 " half3 lightnormal = half3(normalize(LightVector));\n"
3003 "#define lightcolor LightColor\n"
3004 "#endif // MODE_LIGHTDIRECTION\n"
3005 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3007 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3008 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3009 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3010 " // convert modelspace light vector to tangentspace\n"
3011 " half3 lightnormal;\n"
3012 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3013 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3014 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3015 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3016 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3017 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3018 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3019 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3020 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3021 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3022 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3023 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3024 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3025 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3026 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3028 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3029 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3030 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3036 "#ifdef MODE_LIGHTMAP\n"
3037 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3038 "#endif // MODE_LIGHTMAP\n"
3039 "#ifdef MODE_VERTEXCOLOR\n"
3040 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3041 "#endif // MODE_VERTEXCOLOR\n"
3042 "#ifdef MODE_FLATCOLOR\n"
3043 " color.rgb = diffusetex * Color_Ambient;\n"
3044 "#endif // MODE_FLATCOLOR\n"
3050 "# ifdef USEDIFFUSE\n"
3051 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3052 "# ifdef USESPECULAR\n"
3053 "# ifdef USEEXACTSPECULARMATH\n"
3054 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3056 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3057 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3059 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3061 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3064 " color.rgb = diffusetex * Color_Ambient;\n"
3068 "#ifdef USEDEFERREDLIGHTMAP\n"
3069 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3070 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3071 " color.rgb += glosstex * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3075 "#ifdef USEVERTEXTEXTUREBLEND\n"
3076 " color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3078 " color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3083 "#ifdef MODE_LIGHTSOURCE\n"
3084 " color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3086 " color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3090 " // 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"
3091 "#ifdef USEREFLECTION\n"
3092 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3093 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3094 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3095 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3096 " // FIXME temporary hack to detect the case that the reflection\n"
3097 " // gets blackened at edges due to leaving the area that contains actual\n"
3099 " // Remove this 'ack once we have a better way to stop this thing from\n"
3101 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3102 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3103 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3104 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3105 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3106 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3109 " gl_FragColor = float4(color);\n"
3111 "#endif // FRAGMENT_SHADER\n"
3113 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3114 "#endif // !MODE_DEFERREDGEOMETRY\n"
3115 "#endif // !MODE_WATER\n"
3116 "#endif // !MODE_REFRACTION\n"
3117 "#endif // !MODE_BLOOMBLUR\n"
3118 "#endif // !MODE_GENERIC\n"
3119 "#endif // !MODE_POSTPROCESS\n"
3120 "#endif // !MODE_SHOWDEPTH\n"
3121 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3124 //=======================================================================================================================================================
3126 typedef struct shaderpermutationinfo_s
3128 const char *pretext;
3131 shaderpermutationinfo_t;
3133 typedef struct shadermodeinfo_s
3135 const char *vertexfilename;
3136 const char *geometryfilename;
3137 const char *fragmentfilename;
3138 const char *pretext;
3143 typedef enum shaderpermutation_e
3145 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3146 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3147 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3148 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3149 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3150 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3151 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3152 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3153 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3154 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3155 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3156 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3157 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3158 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3159 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3160 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3161 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3162 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3163 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3164 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3165 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3166 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3167 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3168 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3169 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3170 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3171 SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3172 SHADERPERMUTATION_COUNT = 26 ///< size of shaderpermutationinfo array
3174 shaderpermutation_t;
3176 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3177 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3179 {"#define USEDIFFUSE\n", " diffuse"},
3180 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3181 {"#define USEVIEWTINT\n", " viewtint"},
3182 {"#define USECOLORMAPPING\n", " colormapping"},
3183 {"#define USESATURATION\n", " saturation"},
3184 {"#define USEFOGINSIDE\n", " foginside"},
3185 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3186 {"#define USEGAMMARAMPS\n", " gammaramps"},
3187 {"#define USECUBEFILTER\n", " cubefilter"},
3188 {"#define USEGLOW\n", " glow"},
3189 {"#define USEBLOOM\n", " bloom"},
3190 {"#define USESPECULAR\n", " specular"},
3191 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3192 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3193 {"#define USEREFLECTION\n", " reflection"},
3194 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3195 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3196 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3197 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3198 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3199 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3200 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3201 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3202 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3203 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3204 {"#define USEALPHAKILL\n", " alphakill"},
3207 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3208 typedef enum shadermode_e
3210 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3211 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3212 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3213 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3214 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3215 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3216 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3217 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3218 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3219 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3220 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3221 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3222 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3223 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3224 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3229 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3230 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3232 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3233 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3234 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3235 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3236 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3237 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3238 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3239 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3240 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3241 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3242 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3243 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3244 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3245 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3246 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3250 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3252 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3253 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3254 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3255 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3256 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3257 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3258 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3259 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3260 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3261 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3262 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3263 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3264 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3265 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3266 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3270 struct r_glsl_permutation_s;
3271 typedef struct r_glsl_permutation_s
3273 /// hash lookup data
3274 struct r_glsl_permutation_s *hashnext;
3276 unsigned int permutation;
3278 /// indicates if we have tried compiling this permutation already
3280 /// 0 if compilation failed
3282 /// locations of detected uniforms in program object, or -1 if not found
3283 int loc_Texture_First;
3284 int loc_Texture_Second;
3285 int loc_Texture_GammaRamps;
3286 int loc_Texture_Normal;
3287 int loc_Texture_Color;
3288 int loc_Texture_Gloss;
3289 int loc_Texture_Glow;
3290 int loc_Texture_SecondaryNormal;
3291 int loc_Texture_SecondaryColor;
3292 int loc_Texture_SecondaryGloss;
3293 int loc_Texture_SecondaryGlow;
3294 int loc_Texture_Pants;
3295 int loc_Texture_Shirt;
3296 int loc_Texture_FogMask;
3297 int loc_Texture_Lightmap;
3298 int loc_Texture_Deluxemap;
3299 int loc_Texture_Attenuation;
3300 int loc_Texture_Cube;
3301 int loc_Texture_Refraction;
3302 int loc_Texture_Reflection;
3303 int loc_Texture_ShadowMapRect;
3304 int loc_Texture_ShadowMapCube;
3305 int loc_Texture_ShadowMap2D;
3306 int loc_Texture_CubeProjection;
3307 int loc_Texture_ScreenDepth;
3308 int loc_Texture_ScreenNormalMap;
3309 int loc_Texture_ScreenDiffuse;
3310 int loc_Texture_ScreenSpecular;
3312 int loc_BloomBlur_Parameters;
3314 int loc_Color_Ambient;
3315 int loc_Color_Diffuse;
3316 int loc_Color_Specular;
3318 int loc_Color_Pants;
3319 int loc_Color_Shirt;
3320 int loc_DeferredColor_Ambient;
3321 int loc_DeferredColor_Diffuse;
3322 int loc_DeferredColor_Specular;
3323 int loc_DeferredMod_Diffuse;
3324 int loc_DeferredMod_Specular;
3325 int loc_DistortScaleRefractReflect;
3326 int loc_EyePosition;
3328 int loc_FogHeightFade;
3330 int loc_FogPlaneViewDist;
3331 int loc_FogRangeRecip;
3334 int loc_LightPosition;
3335 int loc_OffsetMapping_Scale;
3337 int loc_ReflectColor;
3338 int loc_ReflectFactor;
3339 int loc_ReflectOffset;
3340 int loc_RefractColor;
3342 int loc_ScreenCenterRefractReflect;
3343 int loc_ScreenScaleRefractReflect;
3344 int loc_ScreenToDepth;
3345 int loc_ShadowMap_Parameters;
3346 int loc_ShadowMap_TextureScale;
3347 int loc_SpecularPower;
3352 int loc_ViewTintColor;
3353 int loc_ViewToLight;
3354 int loc_ModelToLight;
3356 int loc_BackgroundTexMatrix;
3357 int loc_ModelViewProjectionMatrix;
3358 int loc_ModelViewMatrix;
3359 int loc_PixelToScreenTexCoord;
3361 r_glsl_permutation_t;
3363 #define SHADERPERMUTATION_HASHSIZE 256
3365 /// information about each possible shader permutation
3366 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3367 /// currently selected permutation
3368 r_glsl_permutation_t *r_glsl_permutation;
3369 /// storage for permutations linked in the hash table
3370 memexpandablearray_t r_glsl_permutationarray;
3372 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3374 //unsigned int hashdepth = 0;
3375 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3376 r_glsl_permutation_t *p;
3377 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3379 if (p->mode == mode && p->permutation == permutation)
3381 //if (hashdepth > 10)
3382 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3387 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3389 p->permutation = permutation;
3390 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3391 r_glsl_permutationhash[mode][hashindex] = p;
3392 //if (hashdepth > 10)
3393 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3397 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3400 if (!filename || !filename[0])
3402 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3405 if (printfromdisknotice)
3406 Con_DPrintf("from disk %s... ", filename);
3407 return shaderstring;
3409 else if (!strcmp(filename, "glsl/default.glsl"))
3411 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3412 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3414 return shaderstring;
3417 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3420 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3421 int vertstrings_count = 0;
3422 int geomstrings_count = 0;
3423 int fragstrings_count = 0;
3424 char *vertexstring, *geometrystring, *fragmentstring;
3425 const char *vertstrings_list[32+3];
3426 const char *geomstrings_list[32+3];
3427 const char *fragstrings_list[32+3];
3428 char permutationname[256];
3435 permutationname[0] = 0;
3436 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3437 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3438 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3440 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3442 // the first pretext is which type of shader to compile as
3443 // (later these will all be bound together as a program object)
3444 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3445 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3446 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3448 // the second pretext is the mode (for example a light source)
3449 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3450 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3451 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3452 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3454 // now add all the permutation pretexts
3455 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3457 if (permutation & (1<<i))
3459 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3460 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3461 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3462 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3466 // keep line numbers correct
3467 vertstrings_list[vertstrings_count++] = "\n";
3468 geomstrings_list[geomstrings_count++] = "\n";
3469 fragstrings_list[fragstrings_count++] = "\n";
3473 // now append the shader text itself
3474 vertstrings_list[vertstrings_count++] = vertexstring;
3475 geomstrings_list[geomstrings_count++] = geometrystring;
3476 fragstrings_list[fragstrings_count++] = fragmentstring;
3478 // if any sources were NULL, clear the respective list
3480 vertstrings_count = 0;
3481 if (!geometrystring)
3482 geomstrings_count = 0;
3483 if (!fragmentstring)
3484 fragstrings_count = 0;
3486 // compile the shader program
3487 if (vertstrings_count + geomstrings_count + fragstrings_count)
3488 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3492 qglUseProgramObjectARB(p->program);CHECKGLERROR
3493 // look up all the uniform variable names we care about, so we don't
3494 // have to look them up every time we set them
3496 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3497 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3498 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3499 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3500 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3501 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3502 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3503 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3504 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3505 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3506 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3507 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3508 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3509 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3510 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3511 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3512 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3513 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3514 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3515 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3516 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3517 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3518 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3519 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3520 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3521 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3522 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3523 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3524 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3525 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3526 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3527 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3528 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3529 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3530 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3531 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3532 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3533 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3534 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3535 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3536 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3537 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3538 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3539 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3540 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3541 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3542 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3543 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3544 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3545 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3546 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3547 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3548 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3549 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3550 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3551 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3552 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3553 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3554 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3555 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3556 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3557 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3558 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3559 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3560 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3561 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3562 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3563 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3564 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3565 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3566 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3567 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3568 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3569 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3570 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3571 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3572 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3573 // initialize the samplers to refer to the texture units we use
3574 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3575 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3576 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3577 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3578 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3579 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3580 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3581 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3582 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3583 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3584 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3585 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3586 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3587 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3588 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3589 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3590 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3591 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3592 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3593 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3594 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
3595 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3596 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3597 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3598 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3599 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3600 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3601 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3603 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3606 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3610 Mem_Free(vertexstring);
3612 Mem_Free(geometrystring);
3614 Mem_Free(fragmentstring);
3617 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3619 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3620 if (r_glsl_permutation != perm)
3622 r_glsl_permutation = perm;
3623 if (!r_glsl_permutation->program)
3625 if (!r_glsl_permutation->compiled)
3626 R_GLSL_CompilePermutation(perm, mode, permutation);
3627 if (!r_glsl_permutation->program)
3629 // remove features until we find a valid permutation
3631 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3633 // reduce i more quickly whenever it would not remove any bits
3634 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3635 if (!(permutation & j))
3638 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3639 if (!r_glsl_permutation->compiled)
3640 R_GLSL_CompilePermutation(perm, mode, permutation);
3641 if (r_glsl_permutation->program)
3644 if (i >= SHADERPERMUTATION_COUNT)
3646 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3647 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3648 qglUseProgramObjectARB(0);CHECKGLERROR
3649 return; // no bit left to clear, entire mode is broken
3654 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3656 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3657 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3661 #include <Cg/cgGL.h>
3662 struct r_cg_permutation_s;
3663 typedef struct r_cg_permutation_s
3665 /// hash lookup data
3666 struct r_cg_permutation_s *hashnext;
3668 unsigned int permutation;
3670 /// indicates if we have tried compiling this permutation already
3672 /// 0 if compilation failed
3675 /// locations of detected parameters in programs, or NULL if not found
3676 CGparameter vp_EyePosition;
3677 CGparameter vp_FogPlane;
3678 CGparameter vp_LightDir;
3679 CGparameter vp_LightPosition;
3680 CGparameter vp_ModelToLight;
3681 CGparameter vp_TexMatrix;
3682 CGparameter vp_BackgroundTexMatrix;
3683 CGparameter vp_ModelViewProjectionMatrix;
3684 CGparameter vp_ModelViewMatrix;
3686 CGparameter fp_Texture_First;
3687 CGparameter fp_Texture_Second;
3688 CGparameter fp_Texture_GammaRamps;
3689 CGparameter fp_Texture_Normal;
3690 CGparameter fp_Texture_Color;
3691 CGparameter fp_Texture_Gloss;
3692 CGparameter fp_Texture_Glow;
3693 CGparameter fp_Texture_SecondaryNormal;
3694 CGparameter fp_Texture_SecondaryColor;
3695 CGparameter fp_Texture_SecondaryGloss;
3696 CGparameter fp_Texture_SecondaryGlow;
3697 CGparameter fp_Texture_Pants;
3698 CGparameter fp_Texture_Shirt;
3699 CGparameter fp_Texture_FogMask;
3700 CGparameter fp_Texture_Lightmap;
3701 CGparameter fp_Texture_Deluxemap;
3702 CGparameter fp_Texture_Attenuation;
3703 CGparameter fp_Texture_Cube;
3704 CGparameter fp_Texture_Refraction;
3705 CGparameter fp_Texture_Reflection;
3706 CGparameter fp_Texture_ShadowMapRect;
3707 CGparameter fp_Texture_ShadowMapCube;
3708 CGparameter fp_Texture_ShadowMap2D;
3709 CGparameter fp_Texture_CubeProjection;
3710 CGparameter fp_Texture_ScreenDepth;
3711 CGparameter fp_Texture_ScreenNormalMap;
3712 CGparameter fp_Texture_ScreenDiffuse;
3713 CGparameter fp_Texture_ScreenSpecular;
3714 CGparameter fp_Alpha;
3715 CGparameter fp_BloomBlur_Parameters;
3716 CGparameter fp_ClientTime;
3717 CGparameter fp_Color_Ambient;
3718 CGparameter fp_Color_Diffuse;
3719 CGparameter fp_Color_Specular;
3720 CGparameter fp_Color_Glow;
3721 CGparameter fp_Color_Pants;
3722 CGparameter fp_Color_Shirt;
3723 CGparameter fp_DeferredColor_Ambient;
3724 CGparameter fp_DeferredColor_Diffuse;
3725 CGparameter fp_DeferredColor_Specular;
3726 CGparameter fp_DeferredMod_Diffuse;
3727 CGparameter fp_DeferredMod_Specular;
3728 CGparameter fp_DistortScaleRefractReflect;
3729 CGparameter fp_EyePosition;
3730 CGparameter fp_FogColor;
3731 CGparameter fp_FogHeightFade;
3732 CGparameter fp_FogPlane;
3733 CGparameter fp_FogPlaneViewDist;
3734 CGparameter fp_FogRangeRecip;
3735 CGparameter fp_LightColor;
3736 CGparameter fp_LightDir;
3737 CGparameter fp_LightPosition;
3738 CGparameter fp_OffsetMapping_Scale;
3739 CGparameter fp_PixelSize;
3740 CGparameter fp_ReflectColor;
3741 CGparameter fp_ReflectFactor;
3742 CGparameter fp_ReflectOffset;
3743 CGparameter fp_RefractColor;
3744 CGparameter fp_Saturation;
3745 CGparameter fp_ScreenCenterRefractReflect;
3746 CGparameter fp_ScreenScaleRefractReflect;
3747 CGparameter fp_ScreenToDepth;
3748 CGparameter fp_ShadowMap_Parameters;
3749 CGparameter fp_ShadowMap_TextureScale;
3750 CGparameter fp_SpecularPower;
3751 CGparameter fp_UserVec1;
3752 CGparameter fp_UserVec2;
3753 CGparameter fp_UserVec3;
3754 CGparameter fp_UserVec4;
3755 CGparameter fp_ViewTintColor;
3756 CGparameter fp_ViewToLight;
3757 CGparameter fp_PixelToScreenTexCoord;
3761 /// information about each possible shader permutation
3762 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3763 /// currently selected permutation
3764 r_cg_permutation_t *r_cg_permutation;
3765 /// storage for permutations linked in the hash table
3766 memexpandablearray_t r_cg_permutationarray;
3768 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
3770 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3772 //unsigned int hashdepth = 0;
3773 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3774 r_cg_permutation_t *p;
3775 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3777 if (p->mode == mode && p->permutation == permutation)
3779 //if (hashdepth > 10)
3780 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3785 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3787 p->permutation = permutation;
3788 p->hashnext = r_cg_permutationhash[mode][hashindex];
3789 r_cg_permutationhash[mode][hashindex] = p;
3790 //if (hashdepth > 10)
3791 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3795 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3798 if (!filename || !filename[0])
3800 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3803 if (printfromdisknotice)
3804 Con_DPrintf("from disk %s... ", filename);
3805 return shaderstring;
3807 else if (!strcmp(filename, "cg/default.cg"))
3809 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3810 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3812 return shaderstring;
3815 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3818 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3819 int vertstrings_count = 0, vertstring_length = 0;
3820 int geomstrings_count = 0, geomstring_length = 0;
3821 int fragstrings_count = 0, fragstring_length = 0;
3823 char *vertexstring, *geometrystring, *fragmentstring;
3824 char *vertstring, *geomstring, *fragstring;
3825 const char *vertstrings_list[32+3];
3826 const char *geomstrings_list[32+3];
3827 const char *fragstrings_list[32+3];
3828 char permutationname[256];
3829 CGprofile vertexProfile;
3830 CGprofile fragmentProfile;
3838 permutationname[0] = 0;
3839 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
3840 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3841 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3843 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3845 // the first pretext is which type of shader to compile as
3846 // (later these will all be bound together as a program object)
3847 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3848 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3849 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3851 // the second pretext is the mode (for example a light source)
3852 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3853 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3854 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3855 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3857 // now add all the permutation pretexts
3858 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3860 if (permutation & (1<<i))
3862 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3863 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3864 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3865 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3869 // keep line numbers correct
3870 vertstrings_list[vertstrings_count++] = "\n";
3871 geomstrings_list[geomstrings_count++] = "\n";
3872 fragstrings_list[fragstrings_count++] = "\n";
3876 // now append the shader text itself
3877 vertstrings_list[vertstrings_count++] = vertexstring;
3878 geomstrings_list[geomstrings_count++] = geometrystring;
3879 fragstrings_list[fragstrings_count++] = fragmentstring;
3881 // if any sources were NULL, clear the respective list
3883 vertstrings_count = 0;
3884 if (!geometrystring)
3885 geomstrings_count = 0;
3886 if (!fragmentstring)
3887 fragstrings_count = 0;
3889 vertstring_length = 0;
3890 for (i = 0;i < vertstrings_count;i++)
3891 vertstring_length += strlen(vertstrings_list[i]);
3892 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3893 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3894 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3896 geomstring_length = 0;
3897 for (i = 0;i < geomstrings_count;i++)
3898 geomstring_length += strlen(geomstrings_list[i]);
3899 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3900 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3901 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3903 fragstring_length = 0;
3904 for (i = 0;i < fragstrings_count;i++)
3905 fragstring_length += strlen(fragstrings_list[i]);
3906 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3907 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3908 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3912 //vertexProfile = CG_PROFILE_ARBVP1;
3913 //fragmentProfile = CG_PROFILE_ARBFP1;
3914 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3915 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3916 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3917 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3918 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3921 // compile the vertex program
3922 if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL)))
3926 cgCompileProgram(p->vprogram);CHECKCGERROR
3927 if (!cgIsProgramCompiled(p->vprogram))
3930 cgDestroyProgram(p->vprogram);CHECKCGERROR
3936 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3937 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3938 // look up all the uniform variable names we care about, so we don't
3939 // have to look them up every time we set them
3941 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
3942 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
3943 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
3944 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
3945 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
3946 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
3947 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3948 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3949 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3954 // compile the fragment program
3955 if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL)))
3958 cgCompileProgram(p->fprogram);CHECKCGERROR
3959 if (!cgIsProgramCompiled(p->fprogram))
3962 cgDestroyProgram(p->fprogram);CHECKCGERROR
3968 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3969 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3971 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
3972 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
3973 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3974 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3975 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
3976 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3977 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3978 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3979 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3980 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3981 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3982 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3983 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3984 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3985 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3986 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3987 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3988 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3989 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3990 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3991 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3992 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3993 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3994 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3995 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3996 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3997 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3998 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3999 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4000 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4001 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4002 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4003 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4004 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4005 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4006 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4007 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4008 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4009 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4010 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4011 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4012 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4013 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4014 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4015 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4016 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4017 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4018 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4019 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4020 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4021 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4022 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4023 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4024 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4025 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4026 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4027 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4028 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4029 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4030 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4031 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4032 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4033 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4034 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4035 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4036 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4037 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4038 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4039 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4040 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4041 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4042 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4047 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4048 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4050 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4054 Mem_Free(vertstring);
4056 Mem_Free(geomstring);
4058 Mem_Free(fragstring);
4060 Mem_Free(vertexstring);
4062 Mem_Free(geometrystring);
4064 Mem_Free(fragmentstring);
4067 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4069 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4072 if (r_cg_permutation != perm)
4074 r_cg_permutation = perm;
4075 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4077 if (!r_cg_permutation->compiled)
4078 R_CG_CompilePermutation(perm, mode, permutation);
4079 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4081 // remove features until we find a valid permutation
4083 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4085 // reduce i more quickly whenever it would not remove any bits
4086 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4087 if (!(permutation & j))
4090 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4091 if (!r_cg_permutation->compiled)
4092 R_CG_CompilePermutation(perm, mode, permutation);
4093 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4096 if (i >= SHADERPERMUTATION_COUNT)
4098 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4099 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4100 return; // no bit left to clear, entire mode is broken
4106 if (r_cg_permutation->vprogram)
4108 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4109 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4110 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4114 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4115 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4117 if (r_cg_permutation->fprogram)
4119 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4120 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4121 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4125 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4126 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4130 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4131 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4134 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4136 cgGLSetTextureParameter(param, R_GetTexture(tex));
4137 cgGLEnableTextureParameter(param);
4141 void R_GLSL_Restart_f(void)
4143 unsigned int i, limit;
4144 switch(vid.renderpath)
4146 case RENDERPATH_GL20:
4148 r_glsl_permutation_t *p;
4149 r_glsl_permutation = NULL;
4150 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4151 for (i = 0;i < limit;i++)
4153 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4155 GL_Backend_FreeProgram(p->program);
4156 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4159 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4162 case RENDERPATH_CGGL:
4165 r_cg_permutation_t *p;
4166 r_cg_permutation = NULL;
4167 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4168 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4169 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4170 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4171 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4172 for (i = 0;i < limit;i++)
4174 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4177 cgDestroyProgram(p->vprogram);
4179 cgDestroyProgram(p->fprogram);
4180 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4183 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4187 case RENDERPATH_GL13:
4188 case RENDERPATH_GL11:
4193 void R_GLSL_DumpShader_f(void)
4198 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4201 FS_Print(file, "/* The engine may define the following macros:\n");
4202 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4203 for (i = 0;i < SHADERMODE_COUNT;i++)
4204 FS_Print(file, glslshadermodeinfo[i].pretext);
4205 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4206 FS_Print(file, shaderpermutationinfo[i].pretext);
4207 FS_Print(file, "*/\n");
4208 FS_Print(file, builtinshaderstring);
4210 Con_Printf("glsl/default.glsl written\n");
4213 Con_Printf("failed to write to glsl/default.glsl\n");
4216 file = FS_OpenRealFile("cg/default.cg", "w", false);
4219 FS_Print(file, "/* The engine may define the following macros:\n");
4220 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4221 for (i = 0;i < SHADERMODE_COUNT;i++)
4222 FS_Print(file, cgshadermodeinfo[i].pretext);
4223 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4224 FS_Print(file, shaderpermutationinfo[i].pretext);
4225 FS_Print(file, "*/\n");
4226 FS_Print(file, builtincgshaderstring);
4228 Con_Printf("cg/default.cg written\n");
4231 Con_Printf("failed to write to cg/default.cg\n");
4235 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4238 texturemode = GL_MODULATE;
4239 switch (vid.renderpath)
4241 case RENDERPATH_GL20:
4242 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))));
4243 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4244 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4246 case RENDERPATH_CGGL:
4249 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))));
4250 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4251 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4254 case RENDERPATH_GL13:
4255 R_Mesh_TexBind(0, first );
4256 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4257 R_Mesh_TexBind(1, second);
4259 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4261 case RENDERPATH_GL11:
4262 R_Mesh_TexBind(0, first );
4267 void R_SetupShader_DepthOrShadow(void)
4269 switch (vid.renderpath)
4271 case RENDERPATH_GL20:
4272 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4274 case RENDERPATH_CGGL:
4276 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4279 case RENDERPATH_GL13:
4280 R_Mesh_TexBind(0, 0);
4281 R_Mesh_TexBind(1, 0);
4283 case RENDERPATH_GL11:
4284 R_Mesh_TexBind(0, 0);
4289 void R_SetupShader_ShowDepth(void)
4291 switch (vid.renderpath)
4293 case RENDERPATH_GL20:
4294 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4296 case RENDERPATH_CGGL:
4298 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4301 case RENDERPATH_GL13:
4303 case RENDERPATH_GL11:
4308 extern qboolean r_shadow_usingdeferredprepass;
4309 extern cvar_t r_shadow_deferred_8bitrange;
4310 extern rtexture_t *r_shadow_attenuationgradienttexture;
4311 extern rtexture_t *r_shadow_attenuation2dtexture;
4312 extern rtexture_t *r_shadow_attenuation3dtexture;
4313 extern qboolean r_shadow_usingshadowmaprect;
4314 extern qboolean r_shadow_usingshadowmapcube;
4315 extern qboolean r_shadow_usingshadowmap2d;
4316 extern float r_shadow_shadowmap_texturescale[2];
4317 extern float r_shadow_shadowmap_parameters[4];
4318 extern qboolean r_shadow_shadowmapvsdct;
4319 extern qboolean r_shadow_shadowmapsampler;
4320 extern int r_shadow_shadowmappcf;
4321 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4322 extern rtexture_t *r_shadow_shadowmap2dtexture;
4323 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4324 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4325 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4326 extern int r_shadow_prepass_width;
4327 extern int r_shadow_prepass_height;
4328 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4329 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4330 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4331 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4332 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4334 // select a permutation of the lighting shader appropriate to this
4335 // combination of texture, entity, light source, and fogging, only use the
4336 // minimum features necessary to avoid wasting rendering time in the
4337 // fragment shader on features that are not being used
4338 unsigned int permutation = 0;
4339 unsigned int mode = 0;
4341 if (rsurfacepass == RSURFPASS_BACKGROUND)
4343 // distorted background
4344 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4345 mode = SHADERMODE_WATER;
4347 mode = SHADERMODE_REFRACTION;
4348 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4349 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4350 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4351 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4352 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4353 R_Mesh_ColorPointer(NULL, 0, 0);
4354 GL_AlphaTest(false);
4355 GL_BlendFunc(GL_ONE, GL_ZERO);
4357 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4359 if (r_glsl_offsetmapping.integer)
4361 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4362 if (r_glsl_offsetmapping_reliefmapping.integer)
4363 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4365 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4366 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4367 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4368 permutation |= SHADERPERMUTATION_ALPHAKILL;
4369 // normalmap (deferred prepass), may use alpha test on diffuse
4370 mode = SHADERMODE_DEFERREDGEOMETRY;
4371 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4372 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4373 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4374 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4375 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4376 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4377 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4378 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4379 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4381 R_Mesh_ColorPointer(NULL, 0, 0);
4382 GL_AlphaTest(false);
4383 GL_BlendFunc(GL_ONE, GL_ZERO);
4385 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4387 if (r_glsl_offsetmapping.integer)
4389 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4390 if (r_glsl_offsetmapping_reliefmapping.integer)
4391 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4393 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4394 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4396 mode = SHADERMODE_LIGHTSOURCE;
4397 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4398 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4399 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4400 permutation |= SHADERPERMUTATION_CUBEFILTER;
4401 if (diffusescale > 0)
4402 permutation |= SHADERPERMUTATION_DIFFUSE;
4403 if (specularscale > 0)
4405 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4406 if (r_shadow_glossexact.integer)
4407 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4409 if (r_refdef.fogenabled)
4410 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4411 if (rsurface.texture->colormapping)
4412 permutation |= SHADERPERMUTATION_COLORMAPPING;
4413 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4415 if (r_shadow_usingshadowmaprect)
4416 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4417 if (r_shadow_usingshadowmap2d)
4418 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4419 if (r_shadow_usingshadowmapcube)
4420 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4421 else if(r_shadow_shadowmapvsdct)
4422 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4424 if (r_shadow_shadowmapsampler)
4425 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4426 if (r_shadow_shadowmappcf > 1)
4427 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4428 else if (r_shadow_shadowmappcf)
4429 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4431 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4432 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4434 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4435 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4436 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4440 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4441 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4442 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4444 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4445 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4446 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4448 R_Mesh_ColorPointer(NULL, 0, 0);
4449 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4450 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4452 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4454 if (r_glsl_offsetmapping.integer)
4456 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4457 if (r_glsl_offsetmapping_reliefmapping.integer)
4458 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4460 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4461 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4462 // unshaded geometry (fullbright or ambient model lighting)
4463 mode = SHADERMODE_FLATCOLOR;
4464 ambientscale = diffusescale = specularscale = 0;
4465 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4466 permutation |= SHADERPERMUTATION_GLOW;
4467 if (r_refdef.fogenabled)
4468 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4469 if (rsurface.texture->colormapping)
4470 permutation |= SHADERPERMUTATION_COLORMAPPING;
4471 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4472 permutation |= SHADERPERMUTATION_REFLECTION;
4473 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4474 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4476 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4477 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4478 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4482 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4483 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4484 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4486 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4487 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4488 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4490 R_Mesh_ColorPointer(NULL, 0, 0);
4491 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4492 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4494 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4496 if (r_glsl_offsetmapping.integer)
4498 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4499 if (r_glsl_offsetmapping_reliefmapping.integer)
4500 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4502 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4503 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4504 // directional model lighting
4505 mode = SHADERMODE_LIGHTDIRECTION;
4506 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4507 permutation |= SHADERPERMUTATION_GLOW;
4508 permutation |= SHADERPERMUTATION_DIFFUSE;
4509 if (specularscale > 0)
4511 permutation |= SHADERPERMUTATION_SPECULAR;
4512 if (r_shadow_glossexact.integer)
4513 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4515 if (r_refdef.fogenabled)
4516 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4517 if (rsurface.texture->colormapping)
4518 permutation |= SHADERPERMUTATION_COLORMAPPING;
4519 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4520 permutation |= SHADERPERMUTATION_REFLECTION;
4521 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4522 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4523 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4524 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4526 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4527 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4528 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4532 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4533 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4534 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4536 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4537 R_Mesh_ColorPointer(NULL, 0, 0);
4538 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4539 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4541 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4543 if (r_glsl_offsetmapping.integer)
4545 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4546 if (r_glsl_offsetmapping_reliefmapping.integer)
4547 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4549 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4550 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4551 // ambient model lighting
4552 mode = SHADERMODE_LIGHTDIRECTION;
4553 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4554 permutation |= SHADERPERMUTATION_GLOW;
4555 if (r_refdef.fogenabled)
4556 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4557 if (rsurface.texture->colormapping)
4558 permutation |= SHADERPERMUTATION_COLORMAPPING;
4559 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4560 permutation |= SHADERPERMUTATION_REFLECTION;
4561 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4562 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4563 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4564 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4566 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4567 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4568 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4572 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4573 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4574 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4576 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4577 R_Mesh_ColorPointer(NULL, 0, 0);
4578 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4579 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4583 if (r_glsl_offsetmapping.integer)
4585 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4586 if (r_glsl_offsetmapping_reliefmapping.integer)
4587 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4589 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4590 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4592 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4593 permutation |= SHADERPERMUTATION_GLOW;
4594 if (r_refdef.fogenabled)
4595 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4596 if (rsurface.texture->colormapping)
4597 permutation |= SHADERPERMUTATION_COLORMAPPING;
4598 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4599 permutation |= SHADERPERMUTATION_REFLECTION;
4600 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4601 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4602 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4604 // deluxemapping (light direction texture)
4605 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4606 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4608 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4609 permutation |= SHADERPERMUTATION_DIFFUSE;
4610 if (specularscale > 0)
4612 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4613 if (r_shadow_glossexact.integer)
4614 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4616 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4617 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4618 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4620 R_Mesh_ColorPointer(NULL, 0, 0);
4622 else if (r_glsl_deluxemapping.integer >= 2)
4624 // fake deluxemapping (uniform light direction in tangentspace)
4625 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4626 permutation |= SHADERPERMUTATION_DIFFUSE;
4627 if (specularscale > 0)
4629 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4630 if (r_shadow_glossexact.integer)
4631 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4633 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4634 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4635 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4637 R_Mesh_ColorPointer(NULL, 0, 0);
4639 else if (rsurface.uselightmaptexture)
4641 // ordinary lightmapping (q1bsp, q3bsp)
4642 mode = SHADERMODE_LIGHTMAP;
4643 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4644 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4645 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4647 R_Mesh_ColorPointer(NULL, 0, 0);
4651 // ordinary vertex coloring (q3bsp)
4652 mode = SHADERMODE_VERTEXCOLOR;
4653 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4654 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4656 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4657 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4659 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4660 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4661 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4665 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4666 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4667 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4669 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4670 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4672 switch(vid.renderpath)
4674 case RENDERPATH_GL20:
4675 R_SetupShader_SetPermutationGLSL(mode, permutation);
4676 if (mode == SHADERMODE_LIGHTSOURCE)
4678 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4679 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4680 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4681 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);
4682 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);
4683 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
4685 // additive passes are only darkened by fog, not tinted
4686 if (r_glsl_permutation->loc_FogColor >= 0)
4687 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4688 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]);
4689 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]);
4690 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4694 if (mode == SHADERMODE_FLATCOLOR)
4696 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4698 else if (mode == SHADERMODE_LIGHTDIRECTION)
4700 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]);
4701 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
4702 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4703 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);
4704 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);
4705 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]);
4706 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]);
4710 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]);
4711 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]);
4712 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4713 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);
4714 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);
4716 // additive passes are only darkened by fog, not tinted
4717 if (r_glsl_permutation->loc_FogColor >= 0)
4719 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4720 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4722 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4724 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);
4725 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]);
4726 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]);
4727 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4728 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4729 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4730 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4731 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4733 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4734 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4735 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4736 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4737 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4738 if (r_glsl_permutation->loc_Color_Pants >= 0)
4740 if (rsurface.texture->pantstexture)
4741 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4743 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4745 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4747 if (rsurface.texture->shirttexture)
4748 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4750 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4752 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]);
4753 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4754 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4755 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4756 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4757 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]);
4758 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4760 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
4761 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
4762 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
4763 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
4764 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
4765 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
4766 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
4767 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
4768 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
4769 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
4770 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
4771 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
4772 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
4773 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
4774 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
4775 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap );
4776 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
4777 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white );
4778 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white );
4779 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
4780 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
4781 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
4782 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
4783 if (rsurface.rtlight)
4785 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
4786 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
4787 if (r_shadow_usingshadowmapcube)
4788 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4789 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
4790 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
4794 case RENDERPATH_CGGL:
4796 R_SetupShader_SetPermutationCG(mode, permutation);
4797 if (mode == SHADERMODE_LIGHTSOURCE)
4799 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4800 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4804 if (mode == SHADERMODE_LIGHTDIRECTION)
4806 if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
4809 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4810 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4811 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4812 if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
4815 if (mode == SHADERMODE_LIGHTSOURCE)
4817 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4818 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4819 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);CHECKCGERROR
4820 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);CHECKCGERROR
4821 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
4823 // additive passes are only darkened by fog, not tinted
4824 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4825 if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
4826 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]);CHECKCGERROR
4827 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4831 if (mode == SHADERMODE_FLATCOLOR)
4833 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4835 else if (mode == SHADERMODE_LIGHTDIRECTION)
4837 if (r_cg_permutation->fp_Color_Ambient) 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]);CHECKCGERROR
4838 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
4839 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
4840 if (r_cg_permutation->fp_DeferredMod_Diffuse) 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);CHECKCGERROR
4841 if (r_cg_permutation->fp_DeferredMod_Specular) 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);CHECKCGERROR
4842 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
4843 if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
4847 if (r_cg_permutation->fp_Color_Ambient) 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]);CHECKCGERROR
4848 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
4849 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
4850 if (r_cg_permutation->fp_DeferredMod_Diffuse) 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);CHECKCGERROR
4851 if (r_cg_permutation->fp_DeferredMod_Specular) 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);CHECKCGERROR
4853 // additive passes are only darkened by fog, not tinted
4854 if (r_cg_permutation->fp_FogColor)
4856 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4857 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4859 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4862 if (r_cg_permutation->fp_DistortScaleRefractReflect) 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);CHECKCGERROR
4863 if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
4864 if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
4865 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4866 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4867 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4868 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4869 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4871 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4872 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4873 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4874 if (r_cg_permutation->fp_Color_Pants)
4876 if (rsurface.texture->pantstexture)
4877 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4879 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4882 if (r_cg_permutation->fp_Color_Shirt)
4884 if (rsurface.texture->shirttexture)
4885 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4887 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4890 if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
4891 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4892 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4893 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4894 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4895 if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
4896 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
4898 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
4899 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
4900 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
4901 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
4902 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
4903 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
4904 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
4905 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
4906 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
4907 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
4908 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
4909 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
4910 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
4911 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
4912 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
4913 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
4914 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
4915 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , r_texture_white );CHECKCGERROR
4916 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , r_texture_white );CHECKCGERROR
4917 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
4918 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
4919 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
4920 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
4921 if (rsurface.rtlight)
4923 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
4924 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
4925 if (r_shadow_usingshadowmapcube)
4926 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4927 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
4928 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
4934 case RENDERPATH_GL13:
4935 case RENDERPATH_GL11:
4940 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4942 // select a permutation of the lighting shader appropriate to this
4943 // combination of texture, entity, light source, and fogging, only use the
4944 // minimum features necessary to avoid wasting rendering time in the
4945 // fragment shader on features that are not being used
4946 unsigned int permutation = 0;
4947 unsigned int mode = 0;
4948 const float *lightcolorbase = rtlight->currentcolor;
4949 float ambientscale = rtlight->ambientscale;
4950 float diffusescale = rtlight->diffusescale;
4951 float specularscale = rtlight->specularscale;
4952 // this is the location of the light in view space
4953 vec3_t viewlightorigin;
4954 // this transforms from view space (camera) to light space (cubemap)
4955 matrix4x4_t viewtolight;
4956 matrix4x4_t lighttoview;
4957 float viewtolight16f[16];
4958 float range = 1.0f / r_shadow_deferred_8bitrange.value;
4960 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4961 if (rtlight->currentcubemap != r_texture_whitecube)
4962 permutation |= SHADERPERMUTATION_CUBEFILTER;
4963 if (diffusescale > 0)
4964 permutation |= SHADERPERMUTATION_DIFFUSE;
4965 if (specularscale > 0)
4967 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4968 if (r_shadow_glossexact.integer)
4969 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4971 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4973 if (r_shadow_usingshadowmaprect)
4974 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4975 if (r_shadow_usingshadowmap2d)
4976 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4977 if (r_shadow_usingshadowmapcube)
4978 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4979 else if(r_shadow_shadowmapvsdct)
4980 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4982 if (r_shadow_shadowmapsampler)
4983 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4984 if (r_shadow_shadowmappcf > 1)
4985 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4986 else if (r_shadow_shadowmappcf)
4987 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4989 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4990 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4991 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4992 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4993 switch(vid.renderpath)
4995 case RENDERPATH_GL20:
4996 R_SetupShader_SetPermutationGLSL(mode, permutation);
4997 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4998 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
4999 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);
5000 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);
5001 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);
5002 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]);
5003 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]);
5004 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));
5005 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]);
5006 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5008 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5009 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5010 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5011 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5012 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
5013 if (r_shadow_usingshadowmapcube)
5014 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5015 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5016 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5018 case RENDERPATH_CGGL:
5020 R_SetupShader_SetPermutationCG(mode, permutation);
5021 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5022 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5023 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);CHECKCGERROR
5024 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);CHECKCGERROR
5025 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);CHECKCGERROR
5026 if (r_cg_permutation->fp_ShadowMap_TextureScale ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
5027 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]);CHECKCGERROR
5028 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));CHECKCGERROR
5029 if (r_cg_permutation->fp_ScreenToDepth ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
5030 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5032 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5033 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5034 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5035 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5036 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5037 if (r_shadow_usingshadowmapcube)
5038 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5039 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5040 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5043 case RENDERPATH_GL13:
5044 case RENDERPATH_GL11:
5049 #define SKINFRAME_HASH 1024
5053 int loadsequence; // incremented each level change
5054 memexpandablearray_t array;
5055 skinframe_t *hash[SKINFRAME_HASH];
5058 r_skinframe_t r_skinframe;
5060 void R_SkinFrame_PrepareForPurge(void)
5062 r_skinframe.loadsequence++;
5063 // wrap it without hitting zero
5064 if (r_skinframe.loadsequence >= 200)
5065 r_skinframe.loadsequence = 1;
5068 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5072 // mark the skinframe as used for the purging code
5073 skinframe->loadsequence = r_skinframe.loadsequence;
5076 void R_SkinFrame_Purge(void)
5080 for (i = 0;i < SKINFRAME_HASH;i++)
5082 for (s = r_skinframe.hash[i];s;s = s->next)
5084 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5086 if (s->merged == s->base)
5088 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5089 R_PurgeTexture(s->stain );s->stain = NULL;
5090 R_PurgeTexture(s->merged);s->merged = NULL;
5091 R_PurgeTexture(s->base );s->base = NULL;
5092 R_PurgeTexture(s->pants );s->pants = NULL;
5093 R_PurgeTexture(s->shirt );s->shirt = NULL;
5094 R_PurgeTexture(s->nmap );s->nmap = NULL;
5095 R_PurgeTexture(s->gloss );s->gloss = NULL;
5096 R_PurgeTexture(s->glow );s->glow = NULL;
5097 R_PurgeTexture(s->fog );s->fog = NULL;
5098 s->loadsequence = 0;
5104 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5106 char basename[MAX_QPATH];
5108 Image_StripImageExtension(name, basename, sizeof(basename));
5110 if( last == NULL ) {
5112 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5113 item = r_skinframe.hash[hashindex];
5118 // linearly search through the hash bucket
5119 for( ; item ; item = item->next ) {
5120 if( !strcmp( item->basename, basename ) ) {
5127 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5131 char basename[MAX_QPATH];
5133 Image_StripImageExtension(name, basename, sizeof(basename));
5135 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5136 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5137 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5141 rtexture_t *dyntexture;
5142 // check whether its a dynamic texture
5143 dyntexture = CL_GetDynTexture( basename );
5144 if (!add && !dyntexture)
5146 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5147 memset(item, 0, sizeof(*item));
5148 strlcpy(item->basename, basename, sizeof(item->basename));
5149 item->base = dyntexture; // either NULL or dyntexture handle
5150 item->textureflags = textureflags;
5151 item->comparewidth = comparewidth;
5152 item->compareheight = compareheight;
5153 item->comparecrc = comparecrc;
5154 item->next = r_skinframe.hash[hashindex];
5155 r_skinframe.hash[hashindex] = item;
5157 else if( item->base == NULL )
5159 rtexture_t *dyntexture;
5160 // check whether its a dynamic texture
5161 // 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]
5162 dyntexture = CL_GetDynTexture( basename );
5163 item->base = dyntexture; // either NULL or dyntexture handle
5166 R_SkinFrame_MarkUsed(item);
5170 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5172 unsigned long long avgcolor[5], wsum; \
5180 for(pix = 0; pix < cnt; ++pix) \
5183 for(comp = 0; comp < 3; ++comp) \
5185 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5188 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5190 for(comp = 0; comp < 3; ++comp) \
5191 avgcolor[comp] += getpixel * w; \
5194 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5195 avgcolor[4] += getpixel; \
5197 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5199 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5200 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5201 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5202 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5205 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5208 unsigned char *pixels;
5209 unsigned char *bumppixels;
5210 unsigned char *basepixels = NULL;
5211 int basepixels_width = 0;
5212 int basepixels_height = 0;
5213 skinframe_t *skinframe;
5214 rtexture_t *ddsbase = NULL;
5215 qboolean ddshasalpha = false;
5216 float ddsavgcolor[4];
5217 char basename[MAX_QPATH];
5219 if (cls.state == ca_dedicated)
5222 // return an existing skinframe if already loaded
5223 // if loading of the first image fails, don't make a new skinframe as it
5224 // would cause all future lookups of this to be missing
5225 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5226 if (skinframe && skinframe->base)
5229 Image_StripImageExtension(name, basename, sizeof(basename));
5231 // check for DDS texture file first
5232 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5234 basepixels = loadimagepixelsbgra(name, complain, true);
5235 if (basepixels == NULL)
5239 if (developer_loading.integer)
5240 Con_Printf("loading skin \"%s\"\n", name);
5242 // we've got some pixels to store, so really allocate this new texture now
5244 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5245 skinframe->stain = NULL;
5246 skinframe->merged = NULL;
5247 skinframe->base = NULL;
5248 skinframe->pants = NULL;
5249 skinframe->shirt = NULL;
5250 skinframe->nmap = NULL;
5251 skinframe->gloss = NULL;
5252 skinframe->glow = NULL;
5253 skinframe->fog = NULL;
5254 skinframe->hasalpha = false;
5258 skinframe->base = ddsbase;
5259 skinframe->hasalpha = ddshasalpha;
5260 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5261 if (r_loadfog && skinframe->hasalpha)
5262 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5263 //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]);
5267 basepixels_width = image_width;
5268 basepixels_height = image_height;
5269 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);
5270 if (textureflags & TEXF_ALPHA)
5272 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5274 if (basepixels[j] < 255)
5276 skinframe->hasalpha = true;
5280 if (r_loadfog && skinframe->hasalpha)
5282 // has transparent pixels
5283 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5284 for (j = 0;j < image_width * image_height * 4;j += 4)
5289 pixels[j+3] = basepixels[j+3];
5291 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);
5295 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5296 //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]);
5297 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5298 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5299 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5300 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5305 if (r_loadnormalmap)
5306 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5307 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5309 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5310 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5311 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5314 // _norm is the name used by tenebrae and has been adopted as standard
5315 if (r_loadnormalmap && skinframe->nmap == NULL)
5317 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5319 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);
5323 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5325 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5326 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5327 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);
5329 Mem_Free(bumppixels);
5331 else if (r_shadow_bumpscale_basetexture.value > 0)
5333 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5334 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5335 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);
5338 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5339 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5342 // _luma is supported only for tenebrae compatibility
5343 // _glow is the preferred name
5344 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5346 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);
5347 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5348 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5349 Mem_Free(pixels);pixels = NULL;
5352 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5354 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);
5355 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5356 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5361 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5363 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);
5364 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5365 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5370 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5372 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);
5373 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5374 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5380 Mem_Free(basepixels);
5385 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5386 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5389 unsigned char *temp1, *temp2;
5390 skinframe_t *skinframe;
5392 if (cls.state == ca_dedicated)
5395 // if already loaded just return it, otherwise make a new skinframe
5396 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5397 if (skinframe && skinframe->base)
5400 skinframe->stain = NULL;
5401 skinframe->merged = NULL;
5402 skinframe->base = NULL;
5403 skinframe->pants = NULL;
5404 skinframe->shirt = NULL;
5405 skinframe->nmap = NULL;
5406 skinframe->gloss = NULL;
5407 skinframe->glow = NULL;
5408 skinframe->fog = NULL;
5409 skinframe->hasalpha = false;
5411 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5415 if (developer_loading.integer)
5416 Con_Printf("loading 32bit skin \"%s\"\n", name);
5418 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5420 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5421 temp2 = temp1 + width * height * 4;
5422 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5423 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5426 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5427 if (textureflags & TEXF_ALPHA)
5429 for (i = 3;i < width * height * 4;i += 4)
5431 if (skindata[i] < 255)
5433 skinframe->hasalpha = true;
5437 if (r_loadfog && skinframe->hasalpha)
5439 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5440 memcpy(fogpixels, skindata, width * height * 4);
5441 for (i = 0;i < width * height * 4;i += 4)
5442 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5443 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5444 Mem_Free(fogpixels);
5448 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5449 //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]);
5454 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5458 skinframe_t *skinframe;
5460 if (cls.state == ca_dedicated)
5463 // if already loaded just return it, otherwise make a new skinframe
5464 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5465 if (skinframe && skinframe->base)
5468 skinframe->stain = NULL;
5469 skinframe->merged = NULL;
5470 skinframe->base = NULL;
5471 skinframe->pants = NULL;
5472 skinframe->shirt = NULL;
5473 skinframe->nmap = NULL;
5474 skinframe->gloss = NULL;
5475 skinframe->glow = NULL;
5476 skinframe->fog = NULL;
5477 skinframe->hasalpha = false;
5479 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5483 if (developer_loading.integer)
5484 Con_Printf("loading quake skin \"%s\"\n", name);
5486 // 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)
5487 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5488 memcpy(skinframe->qpixels, skindata, width*height);
5489 skinframe->qwidth = width;
5490 skinframe->qheight = height;
5493 for (i = 0;i < width * height;i++)
5494 featuresmask |= palette_featureflags[skindata[i]];
5496 skinframe->hasalpha = false;
5497 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5498 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5499 skinframe->qgeneratemerged = true;
5500 skinframe->qgeneratebase = skinframe->qhascolormapping;
5501 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5503 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5504 //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]);
5509 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5513 unsigned char *skindata;
5515 if (!skinframe->qpixels)
5518 if (!skinframe->qhascolormapping)
5519 colormapped = false;
5523 if (!skinframe->qgeneratebase)
5528 if (!skinframe->qgeneratemerged)
5532 width = skinframe->qwidth;
5533 height = skinframe->qheight;
5534 skindata = skinframe->qpixels;
5536 if (skinframe->qgeneratenmap)
5538 unsigned char *temp1, *temp2;
5539 skinframe->qgeneratenmap = false;
5540 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5541 temp2 = temp1 + width * height * 4;
5542 // use either a custom palette or the quake palette
5543 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5544 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5545 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5549 if (skinframe->qgenerateglow)
5551 skinframe->qgenerateglow = false;
5552 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5557 skinframe->qgeneratebase = false;
5558 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);
5559 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5560 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5564 skinframe->qgeneratemerged = false;
5565 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5568 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5570 Mem_Free(skinframe->qpixels);
5571 skinframe->qpixels = NULL;
5575 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)
5578 skinframe_t *skinframe;
5580 if (cls.state == ca_dedicated)
5583 // if already loaded just return it, otherwise make a new skinframe
5584 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5585 if (skinframe && skinframe->base)
5588 skinframe->stain = NULL;
5589 skinframe->merged = NULL;
5590 skinframe->base = NULL;
5591 skinframe->pants = NULL;
5592 skinframe->shirt = NULL;
5593 skinframe->nmap = NULL;
5594 skinframe->gloss = NULL;
5595 skinframe->glow = NULL;
5596 skinframe->fog = NULL;
5597 skinframe->hasalpha = false;
5599 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5603 if (developer_loading.integer)
5604 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5606 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5607 if (textureflags & TEXF_ALPHA)
5609 for (i = 0;i < width * height;i++)
5611 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5613 skinframe->hasalpha = true;
5617 if (r_loadfog && skinframe->hasalpha)
5618 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5621 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5622 //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]);
5627 skinframe_t *R_SkinFrame_LoadMissing(void)
5629 skinframe_t *skinframe;
5631 if (cls.state == ca_dedicated)
5634 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5635 skinframe->stain = NULL;
5636 skinframe->merged = NULL;
5637 skinframe->base = NULL;
5638 skinframe->pants = NULL;
5639 skinframe->shirt = NULL;
5640 skinframe->nmap = NULL;
5641 skinframe->gloss = NULL;
5642 skinframe->glow = NULL;
5643 skinframe->fog = NULL;
5644 skinframe->hasalpha = false;
5646 skinframe->avgcolor[0] = rand() / RAND_MAX;
5647 skinframe->avgcolor[1] = rand() / RAND_MAX;
5648 skinframe->avgcolor[2] = rand() / RAND_MAX;
5649 skinframe->avgcolor[3] = 1;
5654 void R_Main_FreeViewCache(void)
5656 if (r_refdef.viewcache.entityvisible)
5657 Mem_Free(r_refdef.viewcache.entityvisible);
5658 if (r_refdef.viewcache.world_pvsbits)
5659 Mem_Free(r_refdef.viewcache.world_pvsbits);
5660 if (r_refdef.viewcache.world_leafvisible)
5661 Mem_Free(r_refdef.viewcache.world_leafvisible);
5662 if (r_refdef.viewcache.world_surfacevisible)
5663 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5664 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5667 void R_Main_ResizeViewCache(void)
5669 int numentities = r_refdef.scene.numentities;
5670 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5671 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5672 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5673 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5674 if (r_refdef.viewcache.maxentities < numentities)
5676 r_refdef.viewcache.maxentities = numentities;
5677 if (r_refdef.viewcache.entityvisible)
5678 Mem_Free(r_refdef.viewcache.entityvisible);
5679 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5681 if (r_refdef.viewcache.world_numclusters != numclusters)
5683 r_refdef.viewcache.world_numclusters = numclusters;
5684 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5685 if (r_refdef.viewcache.world_pvsbits)
5686 Mem_Free(r_refdef.viewcache.world_pvsbits);
5687 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5689 if (r_refdef.viewcache.world_numleafs != numleafs)
5691 r_refdef.viewcache.world_numleafs = numleafs;
5692 if (r_refdef.viewcache.world_leafvisible)
5693 Mem_Free(r_refdef.viewcache.world_leafvisible);
5694 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5696 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5698 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5699 if (r_refdef.viewcache.world_surfacevisible)
5700 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5701 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5705 extern rtexture_t *loadingscreentexture;
5706 void gl_main_start(void)
5708 loadingscreentexture = NULL;
5709 r_texture_blanknormalmap = NULL;
5710 r_texture_white = NULL;
5711 r_texture_grey128 = NULL;
5712 r_texture_black = NULL;
5713 r_texture_whitecube = NULL;
5714 r_texture_normalizationcube = NULL;
5715 r_texture_fogattenuation = NULL;
5716 r_texture_gammaramps = NULL;
5718 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5719 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5721 switch(vid.renderpath)
5723 case RENDERPATH_GL20:
5724 case RENDERPATH_CGGL:
5725 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5726 Cvar_SetValueQuick(&gl_combine, 1);
5727 Cvar_SetValueQuick(&r_glsl, 1);
5728 r_loadnormalmap = true;
5732 case RENDERPATH_GL13:
5733 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5734 Cvar_SetValueQuick(&gl_combine, 1);
5735 Cvar_SetValueQuick(&r_glsl, 0);
5736 r_loadnormalmap = false;
5737 r_loadgloss = false;
5740 case RENDERPATH_GL11:
5741 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5742 Cvar_SetValueQuick(&gl_combine, 0);
5743 Cvar_SetValueQuick(&r_glsl, 0);
5744 r_loadnormalmap = false;
5745 r_loadgloss = false;
5751 R_FrameData_Reset();
5755 memset(r_queries, 0, sizeof(r_queries));
5757 r_qwskincache = NULL;
5758 r_qwskincache_size = 0;
5760 // set up r_skinframe loading system for textures
5761 memset(&r_skinframe, 0, sizeof(r_skinframe));
5762 r_skinframe.loadsequence = 1;
5763 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5765 r_main_texturepool = R_AllocTexturePool();
5766 R_BuildBlankTextures();
5768 if (vid.support.arb_texture_cube_map)
5771 R_BuildNormalizationCube();
5773 r_texture_fogattenuation = NULL;
5774 r_texture_gammaramps = NULL;
5775 //r_texture_fogintensity = NULL;
5776 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5777 memset(&r_waterstate, 0, sizeof(r_waterstate));
5778 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5779 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5781 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5782 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5784 memset(&r_svbsp, 0, sizeof (r_svbsp));
5786 r_refdef.fogmasktable_density = 0;
5789 void gl_main_shutdown(void)
5792 R_FrameData_Reset();
5794 R_Main_FreeViewCache();
5797 qglDeleteQueriesARB(r_maxqueries, r_queries);
5801 memset(r_queries, 0, sizeof(r_queries));
5803 r_qwskincache = NULL;
5804 r_qwskincache_size = 0;
5806 // clear out the r_skinframe state
5807 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5808 memset(&r_skinframe, 0, sizeof(r_skinframe));
5811 Mem_Free(r_svbsp.nodes);
5812 memset(&r_svbsp, 0, sizeof (r_svbsp));
5813 R_FreeTexturePool(&r_main_texturepool);
5814 loadingscreentexture = NULL;
5815 r_texture_blanknormalmap = NULL;
5816 r_texture_white = NULL;
5817 r_texture_grey128 = NULL;
5818 r_texture_black = NULL;
5819 r_texture_whitecube = NULL;
5820 r_texture_normalizationcube = NULL;
5821 r_texture_fogattenuation = NULL;
5822 r_texture_gammaramps = NULL;
5823 //r_texture_fogintensity = NULL;
5824 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5825 memset(&r_waterstate, 0, sizeof(r_waterstate));
5829 extern void CL_ParseEntityLump(char *entitystring);
5830 void gl_main_newmap(void)
5832 // FIXME: move this code to client
5834 char *entities, entname[MAX_QPATH];
5836 Mem_Free(r_qwskincache);
5837 r_qwskincache = NULL;
5838 r_qwskincache_size = 0;
5841 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5842 l = (int)strlen(entname) - 4;
5843 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5845 memcpy(entname + l, ".ent", 5);
5846 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5848 CL_ParseEntityLump(entities);
5853 if (cl.worldmodel->brush.entities)
5854 CL_ParseEntityLump(cl.worldmodel->brush.entities);
5856 R_Main_FreeViewCache();
5858 R_FrameData_Reset();
5861 void GL_Main_Init(void)
5863 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5865 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5866 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5867 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5868 if (gamemode == GAME_NEHAHRA)
5870 Cvar_RegisterVariable (&gl_fogenable);
5871 Cvar_RegisterVariable (&gl_fogdensity);
5872 Cvar_RegisterVariable (&gl_fogred);
5873 Cvar_RegisterVariable (&gl_foggreen);
5874 Cvar_RegisterVariable (&gl_fogblue);
5875 Cvar_RegisterVariable (&gl_fogstart);
5876 Cvar_RegisterVariable (&gl_fogend);
5877 Cvar_RegisterVariable (&gl_skyclip);
5879 Cvar_RegisterVariable(&r_motionblur);
5880 Cvar_RegisterVariable(&r_motionblur_maxblur);
5881 Cvar_RegisterVariable(&r_motionblur_bmin);
5882 Cvar_RegisterVariable(&r_motionblur_vmin);
5883 Cvar_RegisterVariable(&r_motionblur_vmax);
5884 Cvar_RegisterVariable(&r_motionblur_vcoeff);
5885 Cvar_RegisterVariable(&r_motionblur_randomize);
5886 Cvar_RegisterVariable(&r_damageblur);
5887 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5888 Cvar_RegisterVariable(&r_equalize_entities_minambient);
5889 Cvar_RegisterVariable(&r_equalize_entities_by);
5890 Cvar_RegisterVariable(&r_equalize_entities_to);
5891 Cvar_RegisterVariable(&r_depthfirst);
5892 Cvar_RegisterVariable(&r_useinfinitefarclip);
5893 Cvar_RegisterVariable(&r_farclip_base);
5894 Cvar_RegisterVariable(&r_farclip_world);
5895 Cvar_RegisterVariable(&r_nearclip);
5896 Cvar_RegisterVariable(&r_showbboxes);
5897 Cvar_RegisterVariable(&r_showsurfaces);
5898 Cvar_RegisterVariable(&r_showtris);
5899 Cvar_RegisterVariable(&r_shownormals);
5900 Cvar_RegisterVariable(&r_showlighting);
5901 Cvar_RegisterVariable(&r_showshadowvolumes);
5902 Cvar_RegisterVariable(&r_showcollisionbrushes);
5903 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5904 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5905 Cvar_RegisterVariable(&r_showdisabledepthtest);
5906 Cvar_RegisterVariable(&r_drawportals);
5907 Cvar_RegisterVariable(&r_drawentities);
5908 Cvar_RegisterVariable(&r_cullentities_trace);
5909 Cvar_RegisterVariable(&r_cullentities_trace_samples);
5910 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5911 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5912 Cvar_RegisterVariable(&r_cullentities_trace_delay);
5913 Cvar_RegisterVariable(&r_drawviewmodel);
5914 Cvar_RegisterVariable(&r_speeds);
5915 Cvar_RegisterVariable(&r_fullbrights);
5916 Cvar_RegisterVariable(&r_wateralpha);
5917 Cvar_RegisterVariable(&r_dynamic);
5918 Cvar_RegisterVariable(&r_fullbright);
5919 Cvar_RegisterVariable(&r_shadows);
5920 Cvar_RegisterVariable(&r_shadows_darken);
5921 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5922 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5923 Cvar_RegisterVariable(&r_shadows_throwdistance);
5924 Cvar_RegisterVariable(&r_shadows_throwdirection);
5925 Cvar_RegisterVariable(&r_q1bsp_skymasking);
5926 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5927 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5928 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5929 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5930 Cvar_RegisterVariable(&r_fog_exp2);
5931 Cvar_RegisterVariable(&r_drawfog);
5932 Cvar_RegisterVariable(&r_transparentdepthmasking);
5933 Cvar_RegisterVariable(&r_texture_dds_load);
5934 Cvar_RegisterVariable(&r_texture_dds_save);
5935 Cvar_RegisterVariable(&r_textureunits);
5936 Cvar_RegisterVariable(&gl_combine);
5937 Cvar_RegisterVariable(&r_glsl);
5938 Cvar_RegisterVariable(&r_glsl_deluxemapping);
5939 Cvar_RegisterVariable(&r_glsl_offsetmapping);
5940 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5941 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5942 Cvar_RegisterVariable(&r_glsl_postprocess);
5943 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5944 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5945 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5946 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5947 Cvar_RegisterVariable(&r_water);
5948 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5949 Cvar_RegisterVariable(&r_water_clippingplanebias);
5950 Cvar_RegisterVariable(&r_water_refractdistort);
5951 Cvar_RegisterVariable(&r_water_reflectdistort);
5952 Cvar_RegisterVariable(&r_lerpsprites);
5953 Cvar_RegisterVariable(&r_lerpmodels);
5954 Cvar_RegisterVariable(&r_lerplightstyles);
5955 Cvar_RegisterVariable(&r_waterscroll);
5956 Cvar_RegisterVariable(&r_bloom);
5957 Cvar_RegisterVariable(&r_bloom_colorscale);
5958 Cvar_RegisterVariable(&r_bloom_brighten);
5959 Cvar_RegisterVariable(&r_bloom_blur);
5960 Cvar_RegisterVariable(&r_bloom_resolution);
5961 Cvar_RegisterVariable(&r_bloom_colorexponent);
5962 Cvar_RegisterVariable(&r_bloom_colorsubtract);
5963 Cvar_RegisterVariable(&r_hdr);
5964 Cvar_RegisterVariable(&r_hdr_scenebrightness);
5965 Cvar_RegisterVariable(&r_hdr_glowintensity);
5966 Cvar_RegisterVariable(&r_hdr_range);
5967 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5968 Cvar_RegisterVariable(&developer_texturelogging);
5969 Cvar_RegisterVariable(&gl_lightmaps);
5970 Cvar_RegisterVariable(&r_test);
5971 Cvar_RegisterVariable(&r_batchmode);
5972 Cvar_RegisterVariable(&r_glsl_saturation);
5973 Cvar_RegisterVariable(&r_framedatasize);
5974 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5975 Cvar_SetValue("r_fullbrights", 0);
5976 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5978 Cvar_RegisterVariable(&r_track_sprites);
5979 Cvar_RegisterVariable(&r_track_sprites_flags);
5980 Cvar_RegisterVariable(&r_track_sprites_scalew);
5981 Cvar_RegisterVariable(&r_track_sprites_scaleh);
5982 Cvar_RegisterVariable(&r_overheadsprites_perspective);
5983 Cvar_RegisterVariable(&r_overheadsprites_pushback);
5986 extern void R_Textures_Init(void);
5987 extern void GL_Draw_Init(void);
5988 extern void GL_Main_Init(void);
5989 extern void R_Shadow_Init(void);
5990 extern void R_Sky_Init(void);
5991 extern void GL_Surf_Init(void);
5992 extern void R_Particles_Init(void);
5993 extern void R_Explosion_Init(void);
5994 extern void gl_backend_init(void);
5995 extern void Sbar_Init(void);
5996 extern void R_LightningBeams_Init(void);
5997 extern void Mod_RenderInit(void);
5998 extern void Font_Init(void);
6000 void Render_Init(void)
6013 R_LightningBeams_Init();
6022 extern char *ENGINE_EXTENSIONS;
6025 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6026 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6027 gl_version = (const char *)qglGetString(GL_VERSION);
6028 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6032 if (!gl_platformextensions)
6033 gl_platformextensions = "";
6035 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6036 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6037 Con_Printf("GL_VERSION: %s\n", gl_version);
6038 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6039 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6041 VID_CheckExtensions();
6043 // LordHavoc: report supported extensions
6044 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6046 // clear to black (loading plaque will be seen over this)
6048 qglClearColor(0,0,0,1);CHECKGLERROR
6049 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6052 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6056 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6058 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6061 p = r_refdef.view.frustum + i;
6066 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6070 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6074 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6078 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6082 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6086 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6090 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6094 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6102 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6106 for (i = 0;i < numplanes;i++)
6113 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6117 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6121 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6125 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6129 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6133 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6137 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6141 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6149 //==================================================================================
6151 // LordHavoc: this stores temporary data used within the same frame
6153 qboolean r_framedata_failed;
6154 static size_t r_framedata_size;
6155 static size_t r_framedata_current;
6156 static void *r_framedata_base;
6158 void R_FrameData_Reset(void)
6160 if (r_framedata_base)
6161 Mem_Free(r_framedata_base);
6162 r_framedata_base = NULL;
6163 r_framedata_size = 0;
6164 r_framedata_current = 0;
6165 r_framedata_failed = false;
6168 void R_FrameData_NewFrame(void)
6171 if (r_framedata_failed)
6172 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6173 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6174 wantedsize = bound(65536, wantedsize, 128*1024*1024);
6175 if (r_framedata_size != wantedsize)
6177 r_framedata_size = wantedsize;
6178 if (r_framedata_base)
6179 Mem_Free(r_framedata_base);
6180 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6182 r_framedata_current = 0;
6183 r_framedata_failed = false;
6186 void *R_FrameData_Alloc(size_t size)
6190 // align to 16 byte boundary
6191 size = (size + 15) & ~15;
6192 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6193 r_framedata_current += size;
6196 if (r_framedata_current > r_framedata_size)
6197 r_framedata_failed = true;
6199 // return NULL on everything after a failure
6200 if (r_framedata_failed)
6206 void *R_FrameData_Store(size_t size, void *data)
6208 void *d = R_FrameData_Alloc(size);
6210 memcpy(d, data, size);
6214 //==================================================================================
6216 // LordHavoc: animcache originally written by Echon, rewritten since then
6219 * Animation cache prevents re-generating mesh data for an animated model
6220 * multiple times in one frame for lighting, shadowing, reflections, etc.
6223 void R_AnimCache_Free(void)
6227 void R_AnimCache_ClearCache(void)
6230 entity_render_t *ent;
6232 for (i = 0;i < r_refdef.scene.numentities;i++)
6234 ent = r_refdef.scene.entities[i];
6235 ent->animcache_vertex3f = NULL;
6236 ent->animcache_normal3f = NULL;
6237 ent->animcache_svector3f = NULL;
6238 ent->animcache_tvector3f = NULL;
6242 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6244 dp_model_t *model = ent->model;
6246 // see if it's already cached this frame
6247 if (ent->animcache_vertex3f)
6249 // add normals/tangents if needed
6250 if (wantnormals || wanttangents)
6252 if (ent->animcache_normal3f)
6253 wantnormals = false;
6254 if (ent->animcache_svector3f)
6255 wanttangents = false;
6256 if (wantnormals || wanttangents)
6258 numvertices = model->surfmesh.num_vertices;
6260 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6263 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6264 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6266 if (!r_framedata_failed)
6267 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6273 // see if this ent is worth caching
6274 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6276 // get some memory for this entity and generate mesh data
6277 numvertices = model->surfmesh.num_vertices;
6278 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6280 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6283 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6284 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6286 if (!r_framedata_failed)
6287 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6289 return !r_framedata_failed;
6292 void R_AnimCache_CacheVisibleEntities(void)
6295 qboolean wantnormals = !r_showsurfaces.integer;
6296 qboolean wanttangents = !r_showsurfaces.integer;
6298 switch(vid.renderpath)
6300 case RENDERPATH_GL20:
6301 case RENDERPATH_CGGL:
6303 case RENDERPATH_GL13:
6304 case RENDERPATH_GL11:
6305 wanttangents = false;
6309 // TODO: thread this
6310 // NOTE: R_PrepareRTLights() also caches entities
6312 for (i = 0;i < r_refdef.scene.numentities;i++)
6313 if (r_refdef.viewcache.entityvisible[i])
6314 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6316 if (r_shadows.integer)
6317 for (i = 0;i < r_refdef.scene.numentities;i++)
6318 if (!r_refdef.viewcache.entityvisible[i])
6319 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6322 //==================================================================================
6324 static void R_View_UpdateEntityLighting (void)
6327 entity_render_t *ent;
6328 vec3_t tempdiffusenormal, avg;
6329 vec_t f, fa, fd, fdd;
6331 for (i = 0;i < r_refdef.scene.numentities;i++)
6333 ent = r_refdef.scene.entities[i];
6335 // skip unseen models
6336 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6340 if (ent->model && ent->model->brush.num_leafs)
6342 // TODO: use modellight for r_ambient settings on world?
6343 VectorSet(ent->modellight_ambient, 0, 0, 0);
6344 VectorSet(ent->modellight_diffuse, 0, 0, 0);
6345 VectorSet(ent->modellight_lightdir, 0, 0, 1);
6349 // fetch the lighting from the worldmodel data
6350 VectorClear(ent->modellight_ambient);
6351 VectorClear(ent->modellight_diffuse);
6352 VectorClear(tempdiffusenormal);
6353 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6356 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6357 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6358 if(ent->flags & RENDER_EQUALIZE)
6360 // first fix up ambient lighting...
6361 if(r_equalize_entities_minambient.value > 0)
6363 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6366 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6367 if(fa < r_equalize_entities_minambient.value * fd)
6370 // fa'/fd' = minambient
6371 // fa'+0.25*fd' = fa+0.25*fd
6373 // fa' = fd' * minambient
6374 // fd'*(0.25+minambient) = fa+0.25*fd
6376 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6377 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6379 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6380 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
6381 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6382 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6387 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6389 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6390 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6393 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6394 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6395 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6401 VectorSet(ent->modellight_ambient, 1, 1, 1);
6403 // move the light direction into modelspace coordinates for lighting code
6404 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6405 if(VectorLength2(ent->modellight_lightdir) == 0)
6406 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6407 VectorNormalize(ent->modellight_lightdir);
6411 #define MAX_LINEOFSIGHTTRACES 64
6413 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6416 vec3_t boxmins, boxmaxs;
6419 dp_model_t *model = r_refdef.scene.worldmodel;
6421 if (!model || !model->brush.TraceLineOfSight)
6424 // expand the box a little
6425 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6426 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6427 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6428 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6429 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6430 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6433 VectorCopy(eye, start);
6434 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6435 if (model->brush.TraceLineOfSight(model, start, end))
6438 // try various random positions
6439 for (i = 0;i < numsamples;i++)
6441 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6442 if (model->brush.TraceLineOfSight(model, start, end))
6450 static void R_View_UpdateEntityVisible (void)
6455 entity_render_t *ent;
6457 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6458 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6460 // worldmodel can check visibility
6461 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6462 for (i = 0;i < r_refdef.scene.numentities;i++)
6464 ent = r_refdef.scene.entities[i];
6465 if (!(ent->flags & renderimask))
6466 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)))
6467 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))
6468 r_refdef.viewcache.entityvisible[i] = true;
6470 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6472 for (i = 0;i < r_refdef.scene.numentities;i++)
6474 ent = r_refdef.scene.entities[i];
6475 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6477 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6479 continue; // temp entities do pvs only
6480 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6481 ent->last_trace_visibility = realtime;
6482 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6483 r_refdef.viewcache.entityvisible[i] = 0;
6490 // no worldmodel or it can't check visibility
6491 for (i = 0;i < r_refdef.scene.numentities;i++)
6493 ent = r_refdef.scene.entities[i];
6494 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));
6499 /// only used if skyrendermasked, and normally returns false
6500 int R_DrawBrushModelsSky (void)
6503 entity_render_t *ent;
6506 for (i = 0;i < r_refdef.scene.numentities;i++)
6508 if (!r_refdef.viewcache.entityvisible[i])
6510 ent = r_refdef.scene.entities[i];
6511 if (!ent->model || !ent->model->DrawSky)
6513 ent->model->DrawSky(ent);
6519 static void R_DrawNoModel(entity_render_t *ent);
6520 static void R_DrawModels(void)
6523 entity_render_t *ent;
6525 for (i = 0;i < r_refdef.scene.numentities;i++)
6527 if (!r_refdef.viewcache.entityvisible[i])
6529 ent = r_refdef.scene.entities[i];
6530 r_refdef.stats.entities++;
6531 if (ent->model && ent->model->Draw != NULL)
6532 ent->model->Draw(ent);
6538 static void R_DrawModelsDepth(void)
6541 entity_render_t *ent;
6543 for (i = 0;i < r_refdef.scene.numentities;i++)
6545 if (!r_refdef.viewcache.entityvisible[i])
6547 ent = r_refdef.scene.entities[i];
6548 if (ent->model && ent->model->DrawDepth != NULL)
6549 ent->model->DrawDepth(ent);
6553 static void R_DrawModelsDebug(void)
6556 entity_render_t *ent;
6558 for (i = 0;i < r_refdef.scene.numentities;i++)
6560 if (!r_refdef.viewcache.entityvisible[i])
6562 ent = r_refdef.scene.entities[i];
6563 if (ent->model && ent->model->DrawDebug != NULL)
6564 ent->model->DrawDebug(ent);
6568 static void R_DrawModelsAddWaterPlanes(void)
6571 entity_render_t *ent;
6573 for (i = 0;i < r_refdef.scene.numentities;i++)
6575 if (!r_refdef.viewcache.entityvisible[i])
6577 ent = r_refdef.scene.entities[i];
6578 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6579 ent->model->DrawAddWaterPlanes(ent);
6583 static void R_View_SetFrustum(void)
6586 double slopex, slopey;
6587 vec3_t forward, left, up, origin;
6589 // we can't trust r_refdef.view.forward and friends in reflected scenes
6590 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6593 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6594 r_refdef.view.frustum[0].normal[1] = 0 - 0;
6595 r_refdef.view.frustum[0].normal[2] = -1 - 0;
6596 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6597 r_refdef.view.frustum[1].normal[1] = 0 + 0;
6598 r_refdef.view.frustum[1].normal[2] = -1 + 0;
6599 r_refdef.view.frustum[2].normal[0] = 0 - 0;
6600 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6601 r_refdef.view.frustum[2].normal[2] = -1 - 0;
6602 r_refdef.view.frustum[3].normal[0] = 0 + 0;
6603 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6604 r_refdef.view.frustum[3].normal[2] = -1 + 0;
6608 zNear = r_refdef.nearclip;
6609 nudge = 1.0 - 1.0 / (1<<23);
6610 r_refdef.view.frustum[4].normal[0] = 0 - 0;
6611 r_refdef.view.frustum[4].normal[1] = 0 - 0;
6612 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6613 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6614 r_refdef.view.frustum[5].normal[0] = 0 + 0;
6615 r_refdef.view.frustum[5].normal[1] = 0 + 0;
6616 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6617 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6623 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6624 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6625 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6626 r_refdef.view.frustum[0].dist = m[15] - m[12];
6628 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6629 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6630 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6631 r_refdef.view.frustum[1].dist = m[15] + m[12];
6633 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6634 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6635 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6636 r_refdef.view.frustum[2].dist = m[15] - m[13];
6638 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6639 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6640 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6641 r_refdef.view.frustum[3].dist = m[15] + m[13];
6643 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6644 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6645 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6646 r_refdef.view.frustum[4].dist = m[15] - m[14];
6648 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6649 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6650 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6651 r_refdef.view.frustum[5].dist = m[15] + m[14];
6654 if (r_refdef.view.useperspective)
6656 slopex = 1.0 / r_refdef.view.frustum_x;
6657 slopey = 1.0 / r_refdef.view.frustum_y;
6658 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6659 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
6660 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
6661 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
6662 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6664 // Leaving those out was a mistake, those were in the old code, and they
6665 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6666 // I couldn't reproduce it after adding those normalizations. --blub
6667 VectorNormalize(r_refdef.view.frustum[0].normal);
6668 VectorNormalize(r_refdef.view.frustum[1].normal);
6669 VectorNormalize(r_refdef.view.frustum[2].normal);
6670 VectorNormalize(r_refdef.view.frustum[3].normal);
6672 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6673 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]);
6674 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]);
6675 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]);
6676 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]);
6678 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6679 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6680 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6681 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6682 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6686 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6687 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6688 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6689 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6690 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6691 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6692 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6693 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6694 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6695 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6697 r_refdef.view.numfrustumplanes = 5;
6699 if (r_refdef.view.useclipplane)
6701 r_refdef.view.numfrustumplanes = 6;
6702 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6705 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6706 PlaneClassify(r_refdef.view.frustum + i);
6708 // LordHavoc: note to all quake engine coders, Quake had a special case
6709 // for 90 degrees which assumed a square view (wrong), so I removed it,
6710 // Quake2 has it disabled as well.
6712 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6713 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6714 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6715 //PlaneClassify(&frustum[0]);
6717 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6718 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6719 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6720 //PlaneClassify(&frustum[1]);
6722 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6723 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6724 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6725 //PlaneClassify(&frustum[2]);
6727 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6728 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6729 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6730 //PlaneClassify(&frustum[3]);
6733 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6734 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6735 //PlaneClassify(&frustum[4]);
6738 void R_View_Update(void)
6740 R_Main_ResizeViewCache();
6741 R_View_SetFrustum();
6742 R_View_WorldVisibility(r_refdef.view.useclipplane);
6743 R_View_UpdateEntityVisible();
6744 R_View_UpdateEntityLighting();
6747 void R_SetupView(qboolean allowwaterclippingplane)
6749 const float *customclipplane = NULL;
6751 if (r_refdef.view.useclipplane && allowwaterclippingplane)
6753 // LordHavoc: couldn't figure out how to make this approach the
6754 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6755 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6756 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6757 dist = r_refdef.view.clipplane.dist;
6758 plane[0] = r_refdef.view.clipplane.normal[0];
6759 plane[1] = r_refdef.view.clipplane.normal[1];
6760 plane[2] = r_refdef.view.clipplane.normal[2];
6762 customclipplane = plane;
6765 if (!r_refdef.view.useperspective)
6766 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);
6767 else if (vid.stencil && r_useinfinitefarclip.integer)
6768 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);
6770 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);
6771 R_SetViewport(&r_refdef.view.viewport);
6774 void R_EntityMatrix(const matrix4x4_t *matrix)
6776 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6778 gl_modelmatrixchanged = false;
6779 gl_modelmatrix = *matrix;
6780 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6781 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6782 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6783 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6785 switch(vid.renderpath)
6787 case RENDERPATH_GL20:
6788 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6789 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6790 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6792 case RENDERPATH_CGGL:
6795 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6796 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6797 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6800 case RENDERPATH_GL13:
6801 case RENDERPATH_GL11:
6802 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6808 void R_ResetViewRendering2D(void)
6810 r_viewport_t viewport;
6813 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6814 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);
6815 R_SetViewport(&viewport);
6816 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6817 GL_Color(1, 1, 1, 1);
6818 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6819 GL_BlendFunc(GL_ONE, GL_ZERO);
6820 GL_AlphaTest(false);
6821 GL_ScissorTest(false);
6822 GL_DepthMask(false);
6823 GL_DepthRange(0, 1);
6824 GL_DepthTest(false);
6825 R_EntityMatrix(&identitymatrix);
6826 R_Mesh_ResetTextureState();
6827 GL_PolygonOffset(0, 0);
6828 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6829 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6830 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6831 qglStencilMask(~0);CHECKGLERROR
6832 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6833 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6834 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6837 void R_ResetViewRendering3D(void)
6842 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6843 GL_Color(1, 1, 1, 1);
6844 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6845 GL_BlendFunc(GL_ONE, GL_ZERO);
6846 GL_AlphaTest(false);
6847 GL_ScissorTest(true);
6849 GL_DepthRange(0, 1);
6851 R_EntityMatrix(&identitymatrix);
6852 R_Mesh_ResetTextureState();
6853 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6854 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6855 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6856 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6857 qglStencilMask(~0);CHECKGLERROR
6858 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6859 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6860 GL_CullFace(r_refdef.view.cullface_back);
6863 void R_RenderScene(void);
6864 void R_RenderWaterPlanes(void);
6866 static void R_Water_StartFrame(void)
6869 int waterwidth, waterheight, texturewidth, textureheight;
6870 r_waterstate_waterplane_t *p;
6872 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6875 switch(vid.renderpath)
6877 case RENDERPATH_GL20:
6878 case RENDERPATH_CGGL:
6880 case RENDERPATH_GL13:
6881 case RENDERPATH_GL11:
6885 // set waterwidth and waterheight to the water resolution that will be
6886 // used (often less than the screen resolution for faster rendering)
6887 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6888 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6890 // calculate desired texture sizes
6891 // can't use water if the card does not support the texture size
6892 if (!r_water.integer || r_showsurfaces.integer)
6893 texturewidth = textureheight = waterwidth = waterheight = 0;
6894 else if (vid.support.arb_texture_non_power_of_two)
6896 texturewidth = waterwidth;
6897 textureheight = waterheight;
6901 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
6902 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
6905 // allocate textures as needed
6906 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6908 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6909 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6911 if (p->texture_refraction)
6912 R_FreeTexture(p->texture_refraction);
6913 p->texture_refraction = NULL;
6914 if (p->texture_reflection)
6915 R_FreeTexture(p->texture_reflection);
6916 p->texture_reflection = NULL;
6918 memset(&r_waterstate, 0, sizeof(r_waterstate));
6919 r_waterstate.texturewidth = texturewidth;
6920 r_waterstate.textureheight = textureheight;
6923 if (r_waterstate.texturewidth)
6925 r_waterstate.enabled = true;
6927 // when doing a reduced render (HDR) we want to use a smaller area
6928 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6929 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6931 // set up variables that will be used in shader setup
6932 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6933 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6934 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6935 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6938 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6939 r_waterstate.numwaterplanes = 0;
6942 void R_Water_AddWaterPlane(msurface_t *surface)
6944 int triangleindex, planeindex;
6950 r_waterstate_waterplane_t *p;
6951 texture_t *t = R_GetCurrentTexture(surface->texture);
6952 // just use the first triangle with a valid normal for any decisions
6953 VectorClear(normal);
6954 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6956 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6957 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6958 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6959 TriangleNormal(vert[0], vert[1], vert[2], normal);
6960 if (VectorLength2(normal) >= 0.001)
6964 VectorCopy(normal, plane.normal);
6965 VectorNormalize(plane.normal);
6966 plane.dist = DotProduct(vert[0], plane.normal);
6967 PlaneClassify(&plane);
6968 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6970 // skip backfaces (except if nocullface is set)
6971 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6973 VectorNegate(plane.normal, plane.normal);
6975 PlaneClassify(&plane);
6979 // find a matching plane if there is one
6980 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6981 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6983 if (planeindex >= r_waterstate.maxwaterplanes)
6984 return; // nothing we can do, out of planes
6986 // if this triangle does not fit any known plane rendered this frame, add one
6987 if (planeindex >= r_waterstate.numwaterplanes)
6989 // store the new plane
6990 r_waterstate.numwaterplanes++;
6992 // clear materialflags and pvs
6993 p->materialflags = 0;
6994 p->pvsvalid = false;
6996 // merge this surface's materialflags into the waterplane
6997 p->materialflags |= t->currentmaterialflags;
6998 // merge this surface's PVS into the waterplane
6999 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7000 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7001 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7003 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7008 static void R_Water_ProcessPlanes(void)
7010 r_refdef_view_t originalview;
7011 r_refdef_view_t myview;
7013 r_waterstate_waterplane_t *p;
7015 originalview = r_refdef.view;
7017 // make sure enough textures are allocated
7018 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7020 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7022 if (!p->texture_refraction)
7023 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7024 if (!p->texture_refraction)
7028 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7030 if (!p->texture_reflection)
7031 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7032 if (!p->texture_reflection)
7038 r_refdef.view = originalview;
7039 r_refdef.view.showdebug = false;
7040 r_refdef.view.width = r_waterstate.waterwidth;
7041 r_refdef.view.height = r_waterstate.waterheight;
7042 r_refdef.view.useclipplane = true;
7043 myview = r_refdef.view;
7044 r_waterstate.renderingscene = true;
7045 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7047 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7049 r_refdef.view = myview;
7050 // render reflected scene and copy into texture
7051 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7052 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7053 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7054 r_refdef.view.clipplane = p->plane;
7055 // reverse the cullface settings for this render
7056 r_refdef.view.cullface_front = GL_FRONT;
7057 r_refdef.view.cullface_back = GL_BACK;
7058 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7060 r_refdef.view.usecustompvs = true;
7062 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7064 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7067 R_ResetViewRendering3D();
7068 R_ClearScreen(r_refdef.fogenabled);
7072 R_Mesh_CopyToTexture(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);
7075 // render the normal view scene and copy into texture
7076 // (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)
7077 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7079 r_refdef.view = myview;
7080 r_refdef.view.clipplane = p->plane;
7081 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7082 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7083 PlaneClassify(&r_refdef.view.clipplane);
7085 R_ResetViewRendering3D();
7086 R_ClearScreen(r_refdef.fogenabled);
7090 R_Mesh_CopyToTexture(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);
7094 r_waterstate.renderingscene = false;
7095 r_refdef.view = originalview;
7096 R_ResetViewRendering3D();
7097 R_ClearScreen(r_refdef.fogenabled);
7101 r_refdef.view = originalview;
7102 r_waterstate.renderingscene = false;
7103 Cvar_SetValueQuick(&r_water, 0);
7104 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
7108 void R_Bloom_StartFrame(void)
7110 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7112 switch(vid.renderpath)
7114 case RENDERPATH_GL20:
7115 case RENDERPATH_CGGL:
7117 case RENDERPATH_GL13:
7118 case RENDERPATH_GL11:
7122 // set bloomwidth and bloomheight to the bloom resolution that will be
7123 // used (often less than the screen resolution for faster rendering)
7124 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7125 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7126 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7127 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7128 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7130 // calculate desired texture sizes
7131 if (vid.support.arb_texture_non_power_of_two)
7133 screentexturewidth = r_refdef.view.width;
7134 screentextureheight = r_refdef.view.height;
7135 bloomtexturewidth = r_bloomstate.bloomwidth;
7136 bloomtextureheight = r_bloomstate.bloomheight;
7140 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
7141 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
7142 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
7143 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
7146 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))
7148 Cvar_SetValueQuick(&r_hdr, 0);
7149 Cvar_SetValueQuick(&r_bloom, 0);
7150 Cvar_SetValueQuick(&r_motionblur, 0);
7151 Cvar_SetValueQuick(&r_damageblur, 0);
7154 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)))
7155 screentexturewidth = screentextureheight = 0;
7156 if (!r_hdr.integer && !r_bloom.integer)
7157 bloomtexturewidth = bloomtextureheight = 0;
7159 // allocate textures as needed
7160 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7162 if (r_bloomstate.texture_screen)
7163 R_FreeTexture(r_bloomstate.texture_screen);
7164 r_bloomstate.texture_screen = NULL;
7165 r_bloomstate.screentexturewidth = screentexturewidth;
7166 r_bloomstate.screentextureheight = screentextureheight;
7167 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7168 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7170 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7172 if (r_bloomstate.texture_bloom)
7173 R_FreeTexture(r_bloomstate.texture_bloom);
7174 r_bloomstate.texture_bloom = NULL;
7175 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7176 r_bloomstate.bloomtextureheight = bloomtextureheight;
7177 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7178 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7181 // when doing a reduced render (HDR) we want to use a smaller area
7182 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7183 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7184 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7185 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7186 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7188 // set up a texcoord array for the full resolution screen image
7189 // (we have to keep this around to copy back during final render)
7190 r_bloomstate.screentexcoord2f[0] = 0;
7191 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7192 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7193 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7194 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7195 r_bloomstate.screentexcoord2f[5] = 0;
7196 r_bloomstate.screentexcoord2f[6] = 0;
7197 r_bloomstate.screentexcoord2f[7] = 0;
7199 // set up a texcoord array for the reduced resolution bloom image
7200 // (which will be additive blended over the screen image)
7201 r_bloomstate.bloomtexcoord2f[0] = 0;
7202 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7203 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7204 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7205 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7206 r_bloomstate.bloomtexcoord2f[5] = 0;
7207 r_bloomstate.bloomtexcoord2f[6] = 0;
7208 r_bloomstate.bloomtexcoord2f[7] = 0;
7210 if (r_hdr.integer || r_bloom.integer)
7212 r_bloomstate.enabled = true;
7213 r_bloomstate.hdr = r_hdr.integer != 0;
7216 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);
7219 void R_Bloom_CopyBloomTexture(float colorscale)
7221 r_refdef.stats.bloom++;
7223 // scale down screen texture to the bloom texture size
7225 R_SetViewport(&r_bloomstate.viewport);
7226 GL_BlendFunc(GL_ONE, GL_ZERO);
7227 GL_Color(colorscale, colorscale, colorscale, 1);
7228 // TODO: optimize with multitexture or GLSL
7229 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7230 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7231 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7232 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7234 // we now have a bloom image in the framebuffer
7235 // copy it into the bloom image texture for later processing
7236 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7237 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7240 void R_Bloom_CopyHDRTexture(void)
7242 R_Mesh_CopyToTexture(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);
7243 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7246 void R_Bloom_MakeTexture(void)
7249 float xoffset, yoffset, r, brighten;
7251 r_refdef.stats.bloom++;
7253 R_ResetViewRendering2D();
7254 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7255 R_Mesh_ColorPointer(NULL, 0, 0);
7257 // we have a bloom image in the framebuffer
7259 R_SetViewport(&r_bloomstate.viewport);
7261 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7264 r = bound(0, r_bloom_colorexponent.value / x, 1);
7265 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7266 GL_Color(r, r, r, 1);
7267 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7268 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7269 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7270 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7272 // copy the vertically blurred bloom view to a texture
7273 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7274 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7277 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7278 brighten = r_bloom_brighten.value;
7280 brighten *= r_hdr_range.value;
7281 brighten = sqrt(brighten);
7283 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7284 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7285 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7287 for (dir = 0;dir < 2;dir++)
7289 // blend on at multiple vertical offsets to achieve a vertical blur
7290 // TODO: do offset blends using GLSL
7291 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7292 GL_BlendFunc(GL_ONE, GL_ZERO);
7293 for (x = -range;x <= range;x++)
7295 if (!dir){xoffset = 0;yoffset = x;}
7296 else {xoffset = x;yoffset = 0;}
7297 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7298 yoffset /= (float)r_bloomstate.bloomtextureheight;
7299 // compute a texcoord array with the specified x and y offset
7300 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7301 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7302 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7303 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7304 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7305 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7306 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7307 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7308 // this r value looks like a 'dot' particle, fading sharply to
7309 // black at the edges
7310 // (probably not realistic but looks good enough)
7311 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7312 //r = brighten/(range*2+1);
7313 r = brighten / (range * 2 + 1);
7315 r *= (1 - x*x/(float)(range*range));
7316 GL_Color(r, r, r, 1);
7317 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7318 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7319 GL_BlendFunc(GL_ONE, GL_ONE);
7322 // copy the vertically blurred bloom view to a texture
7323 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7324 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7327 // apply subtract last
7328 // (just like it would be in a GLSL shader)
7329 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7331 GL_BlendFunc(GL_ONE, GL_ZERO);
7332 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7333 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7334 GL_Color(1, 1, 1, 1);
7335 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7336 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7338 GL_BlendFunc(GL_ONE, GL_ONE);
7339 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7340 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7341 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7342 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7343 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7344 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7345 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7347 // copy the darkened bloom view to a texture
7348 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7349 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7353 void R_HDR_RenderBloomTexture(void)
7355 int oldwidth, oldheight;
7356 float oldcolorscale;
7358 oldcolorscale = r_refdef.view.colorscale;
7359 oldwidth = r_refdef.view.width;
7360 oldheight = r_refdef.view.height;
7361 r_refdef.view.width = r_bloomstate.bloomwidth;
7362 r_refdef.view.height = r_bloomstate.bloomheight;
7364 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
7365 // TODO: add exposure compensation features
7366 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7368 r_refdef.view.showdebug = false;
7369 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7371 R_ResetViewRendering3D();
7373 R_ClearScreen(r_refdef.fogenabled);
7374 if (r_timereport_active)
7375 R_TimeReport("HDRclear");
7378 if (r_timereport_active)
7379 R_TimeReport("visibility");
7381 // only do secondary renders with HDR if r_hdr is 2 or higher
7382 r_waterstate.numwaterplanes = 0;
7383 if (r_waterstate.enabled && r_hdr.integer >= 2)
7384 R_RenderWaterPlanes();
7386 r_refdef.view.showdebug = true;
7388 r_waterstate.numwaterplanes = 0;
7390 R_ResetViewRendering2D();
7392 R_Bloom_CopyHDRTexture();
7393 R_Bloom_MakeTexture();
7395 // restore the view settings
7396 r_refdef.view.width = oldwidth;
7397 r_refdef.view.height = oldheight;
7398 r_refdef.view.colorscale = oldcolorscale;
7400 R_ResetViewRendering3D();
7402 R_ClearScreen(r_refdef.fogenabled);
7403 if (r_timereport_active)
7404 R_TimeReport("viewclear");
7407 static void R_BlendView(void)
7409 unsigned int permutation;
7410 float uservecs[4][4];
7412 switch (vid.renderpath)
7414 case RENDERPATH_GL20:
7415 case RENDERPATH_CGGL:
7417 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7418 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7419 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7420 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7421 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7423 if (r_bloomstate.texture_screen)
7425 // make sure the buffer is available
7426 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7428 R_ResetViewRendering2D();
7429 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7430 R_Mesh_ColorPointer(NULL, 0, 0);
7432 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7434 // declare variables
7436 static float avgspeed;
7438 speed = VectorLength(cl.movement_velocity);
7440 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7441 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7443 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7444 speed = bound(0, speed, 1);
7445 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7447 // calculate values into a standard alpha
7448 cl.motionbluralpha = 1 - exp(-
7450 (r_motionblur.value * speed / 80)
7452 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7455 max(0.0001, cl.time - cl.oldtime) // fps independent
7458 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7459 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7461 if (cl.motionbluralpha > 0)
7463 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7464 GL_Color(1, 1, 1, cl.motionbluralpha);
7465 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7466 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7467 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7468 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7472 // copy view into the screen texture
7473 R_Mesh_CopyToTexture(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);
7474 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7476 else if (!r_bloomstate.texture_bloom)
7478 // we may still have to do view tint...
7479 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7481 // apply a color tint to the whole view
7482 R_ResetViewRendering2D();
7483 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7484 R_Mesh_ColorPointer(NULL, 0, 0);
7485 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7486 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7487 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7488 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7490 break; // no screen processing, no bloom, skip it
7493 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7495 // render simple bloom effect
7496 // copy the screen and shrink it and darken it for the bloom process
7497 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7498 // make the bloom texture
7499 R_Bloom_MakeTexture();
7502 #if _MSC_VER >= 1400
7503 #define sscanf sscanf_s
7505 memset(uservecs, 0, sizeof(uservecs));
7506 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7507 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7508 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7509 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7511 R_ResetViewRendering2D();
7512 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7513 R_Mesh_ColorPointer(NULL, 0, 0);
7514 GL_Color(1, 1, 1, 1);
7515 GL_BlendFunc(GL_ONE, GL_ZERO);
7516 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7517 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7519 switch(vid.renderpath)
7521 case RENDERPATH_GL20:
7522 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7523 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
7524 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
7525 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7526 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]);
7527 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime , cl.time);
7528 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7529 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]);
7530 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]);
7531 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]);
7532 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]);
7533 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7534 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7536 case RENDERPATH_CGGL:
7538 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7539 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
7540 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
7541 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
7542 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]);CHECKCGERROR
7543 if (r_cg_permutation->fp_ClientTime ) cgGLSetParameter1f( r_cg_permutation->fp_ClientTime , cl.time);CHECKCGERROR
7544 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7545 if (r_cg_permutation->fp_UserVec1 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);CHECKCGERROR
7546 if (r_cg_permutation->fp_UserVec2 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);CHECKCGERROR
7547 if (r_cg_permutation->fp_UserVec3 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);CHECKCGERROR
7548 if (r_cg_permutation->fp_UserVec4 ) cgGLSetParameter4f( r_cg_permutation->fp_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);CHECKCGERROR
7549 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
7550 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7556 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7557 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7559 case RENDERPATH_GL13:
7560 case RENDERPATH_GL11:
7561 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7563 // apply a color tint to the whole view
7564 R_ResetViewRendering2D();
7565 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7566 R_Mesh_ColorPointer(NULL, 0, 0);
7567 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7568 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7569 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7570 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7576 matrix4x4_t r_waterscrollmatrix;
7578 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7580 if (r_refdef.fog_density)
7582 r_refdef.fogcolor[0] = r_refdef.fog_red;
7583 r_refdef.fogcolor[1] = r_refdef.fog_green;
7584 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7586 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7587 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7588 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7589 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7593 VectorCopy(r_refdef.fogcolor, fogvec);
7594 // color.rgb *= ContrastBoost * SceneBrightness;
7595 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7596 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7597 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7598 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7603 void R_UpdateVariables(void)
7607 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7609 r_refdef.farclip = r_farclip_base.value;
7610 if (r_refdef.scene.worldmodel)
7611 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7612 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7614 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7615 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7616 r_refdef.polygonfactor = 0;
7617 r_refdef.polygonoffset = 0;
7618 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7619 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7621 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7622 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7623 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7624 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7625 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7626 if (r_showsurfaces.integer)
7628 r_refdef.scene.rtworld = false;
7629 r_refdef.scene.rtworldshadows = false;
7630 r_refdef.scene.rtdlight = false;
7631 r_refdef.scene.rtdlightshadows = false;
7632 r_refdef.lightmapintensity = 0;
7635 if (gamemode == GAME_NEHAHRA)
7637 if (gl_fogenable.integer)
7639 r_refdef.oldgl_fogenable = true;
7640 r_refdef.fog_density = gl_fogdensity.value;
7641 r_refdef.fog_red = gl_fogred.value;
7642 r_refdef.fog_green = gl_foggreen.value;
7643 r_refdef.fog_blue = gl_fogblue.value;
7644 r_refdef.fog_alpha = 1;
7645 r_refdef.fog_start = 0;
7646 r_refdef.fog_end = gl_skyclip.value;
7647 r_refdef.fog_height = 1<<30;
7648 r_refdef.fog_fadedepth = 128;
7650 else if (r_refdef.oldgl_fogenable)
7652 r_refdef.oldgl_fogenable = false;
7653 r_refdef.fog_density = 0;
7654 r_refdef.fog_red = 0;
7655 r_refdef.fog_green = 0;
7656 r_refdef.fog_blue = 0;
7657 r_refdef.fog_alpha = 0;
7658 r_refdef.fog_start = 0;
7659 r_refdef.fog_end = 0;
7660 r_refdef.fog_height = 1<<30;
7661 r_refdef.fog_fadedepth = 128;
7665 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7666 r_refdef.fog_start = max(0, r_refdef.fog_start);
7667 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7669 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7671 if (r_refdef.fog_density && r_drawfog.integer)
7673 r_refdef.fogenabled = true;
7674 // this is the point where the fog reaches 0.9986 alpha, which we
7675 // consider a good enough cutoff point for the texture
7676 // (0.9986 * 256 == 255.6)
7677 if (r_fog_exp2.integer)
7678 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7680 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7681 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7682 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7683 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7684 // fog color was already set
7685 // update the fog texture
7686 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)
7687 R_BuildFogTexture();
7690 r_refdef.fogenabled = false;
7692 switch(vid.renderpath)
7694 case RENDERPATH_GL20:
7695 case RENDERPATH_CGGL:
7696 if(v_glslgamma.integer && !vid_gammatables_trivial)
7698 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7700 // build GLSL gamma texture
7701 #define RAMPWIDTH 256
7702 unsigned short ramp[RAMPWIDTH * 3];
7703 unsigned char rampbgr[RAMPWIDTH][4];
7706 r_texture_gammaramps_serial = vid_gammatables_serial;
7708 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7709 for(i = 0; i < RAMPWIDTH; ++i)
7711 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7712 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7713 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7716 if (r_texture_gammaramps)
7718 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7722 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);
7728 // remove GLSL gamma texture
7731 case RENDERPATH_GL13:
7732 case RENDERPATH_GL11:
7737 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7738 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7744 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7745 if( scenetype != r_currentscenetype ) {
7746 // store the old scenetype
7747 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7748 r_currentscenetype = scenetype;
7749 // move in the new scene
7750 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7759 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7761 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7762 if( scenetype == r_currentscenetype ) {
7763 return &r_refdef.scene;
7765 return &r_scenes_store[ scenetype ];
7774 void R_RenderView(void)
7776 if (r_timereport_active)
7777 R_TimeReport("start");
7778 r_textureframe++; // used only by R_GetCurrentTexture
7779 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7781 if (!r_drawentities.integer)
7782 r_refdef.scene.numentities = 0;
7784 R_AnimCache_ClearCache();
7785 R_FrameData_NewFrame();
7787 if (r_refdef.view.isoverlay)
7789 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7790 GL_Clear( GL_DEPTH_BUFFER_BIT );
7791 R_TimeReport("depthclear");
7793 r_refdef.view.showdebug = false;
7795 r_waterstate.enabled = false;
7796 r_waterstate.numwaterplanes = 0;
7804 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7805 return; //Host_Error ("R_RenderView: NULL worldmodel");
7807 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7809 // break apart the view matrix into vectors for various purposes
7810 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7811 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7812 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7813 VectorNegate(r_refdef.view.left, r_refdef.view.right);
7814 // make an inverted copy of the view matrix for tracking sprites
7815 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7817 R_Shadow_UpdateWorldLightSelection();
7819 R_Bloom_StartFrame();
7820 R_Water_StartFrame();
7823 if (r_timereport_active)
7824 R_TimeReport("viewsetup");
7826 R_ResetViewRendering3D();
7828 if (r_refdef.view.clear || r_refdef.fogenabled)
7830 R_ClearScreen(r_refdef.fogenabled);
7831 if (r_timereport_active)
7832 R_TimeReport("viewclear");
7834 r_refdef.view.clear = true;
7836 // this produces a bloom texture to be used in R_BlendView() later
7837 if (r_hdr.integer && r_bloomstate.bloomwidth)
7839 R_HDR_RenderBloomTexture();
7840 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
7841 r_textureframe++; // used only by R_GetCurrentTexture
7844 r_refdef.view.showdebug = true;
7847 if (r_timereport_active)
7848 R_TimeReport("visibility");
7850 r_waterstate.numwaterplanes = 0;
7851 if (r_waterstate.enabled)
7852 R_RenderWaterPlanes();
7855 r_waterstate.numwaterplanes = 0;
7858 if (r_timereport_active)
7859 R_TimeReport("blendview");
7861 GL_Scissor(0, 0, vid.width, vid.height);
7862 GL_ScissorTest(false);
7866 void R_RenderWaterPlanes(void)
7868 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7870 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7871 if (r_timereport_active)
7872 R_TimeReport("waterworld");
7875 // don't let sound skip if going slow
7876 if (r_refdef.scene.extraupdate)
7879 R_DrawModelsAddWaterPlanes();
7880 if (r_timereport_active)
7881 R_TimeReport("watermodels");
7883 if (r_waterstate.numwaterplanes)
7885 R_Water_ProcessPlanes();
7886 if (r_timereport_active)
7887 R_TimeReport("waterscenes");
7891 extern void R_DrawLightningBeams (void);
7892 extern void VM_CL_AddPolygonsToMeshQueue (void);
7893 extern void R_DrawPortals (void);
7894 extern cvar_t cl_locs_show;
7895 static void R_DrawLocs(void);
7896 static void R_DrawEntityBBoxes(void);
7897 static void R_DrawModelDecals(void);
7898 extern cvar_t cl_decals_newsystem;
7899 extern qboolean r_shadow_usingdeferredprepass;
7900 void R_RenderScene(void)
7902 r_refdef.stats.renders++;
7906 // don't let sound skip if going slow
7907 if (r_refdef.scene.extraupdate)
7910 R_MeshQueue_BeginScene();
7914 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);
7916 if (cl.csqc_vidvars.drawworld)
7918 // don't let sound skip if going slow
7919 if (r_refdef.scene.extraupdate)
7922 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7924 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7925 if (r_timereport_active)
7926 R_TimeReport("worldsky");
7929 if (R_DrawBrushModelsSky() && r_timereport_active)
7930 R_TimeReport("bmodelsky");
7932 if (skyrendermasked && skyrenderlater)
7934 // we have to force off the water clipping plane while rendering sky
7938 if (r_timereport_active)
7939 R_TimeReport("sky");
7943 R_AnimCache_CacheVisibleEntities();
7944 if (r_timereport_active)
7945 R_TimeReport("animation");
7947 R_Shadow_PrepareLights();
7948 if (r_timereport_active)
7949 R_TimeReport("preparelights");
7951 if (r_shadow_usingdeferredprepass)
7952 R_Shadow_DrawPrepass();
7954 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7956 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7957 if (r_timereport_active)
7958 R_TimeReport("worlddepth");
7960 if (r_depthfirst.integer >= 2)
7962 R_DrawModelsDepth();
7963 if (r_timereport_active)
7964 R_TimeReport("modeldepth");
7967 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7969 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7970 if (r_timereport_active)
7971 R_TimeReport("world");
7974 // don't let sound skip if going slow
7975 if (r_refdef.scene.extraupdate)
7979 if (r_timereport_active)
7980 R_TimeReport("models");
7982 // don't let sound skip if going slow
7983 if (r_refdef.scene.extraupdate)
7986 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7988 R_DrawModelShadows();
7989 R_ResetViewRendering3D();
7990 // don't let sound skip if going slow
7991 if (r_refdef.scene.extraupdate)
7995 if (!r_shadow_usingdeferredprepass)
7997 R_Shadow_DrawLights();
7998 if (r_timereport_active)
7999 R_TimeReport("rtlights");
8002 // don't let sound skip if going slow
8003 if (r_refdef.scene.extraupdate)
8006 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8008 R_DrawModelShadows();
8009 R_ResetViewRendering3D();
8010 // don't let sound skip if going slow
8011 if (r_refdef.scene.extraupdate)
8015 if (cl.csqc_vidvars.drawworld)
8017 if (cl_decals_newsystem.integer)
8019 R_DrawModelDecals();
8020 if (r_timereport_active)
8021 R_TimeReport("modeldecals");
8026 if (r_timereport_active)
8027 R_TimeReport("decals");
8031 if (r_timereport_active)
8032 R_TimeReport("particles");
8035 if (r_timereport_active)
8036 R_TimeReport("explosions");
8038 R_DrawLightningBeams();
8039 if (r_timereport_active)
8040 R_TimeReport("lightning");
8043 VM_CL_AddPolygonsToMeshQueue();
8045 if (r_refdef.view.showdebug)
8047 if (cl_locs_show.integer)
8050 if (r_timereport_active)
8051 R_TimeReport("showlocs");
8054 if (r_drawportals.integer)
8057 if (r_timereport_active)
8058 R_TimeReport("portals");
8061 if (r_showbboxes.value > 0)
8063 R_DrawEntityBBoxes();
8064 if (r_timereport_active)
8065 R_TimeReport("bboxes");
8069 R_MeshQueue_RenderTransparent();
8070 if (r_timereport_active)
8071 R_TimeReport("drawtrans");
8073 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))
8075 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8076 if (r_timereport_active)
8077 R_TimeReport("worlddebug");
8078 R_DrawModelsDebug();
8079 if (r_timereport_active)
8080 R_TimeReport("modeldebug");
8083 if (cl.csqc_vidvars.drawworld)
8085 R_Shadow_DrawCoronas();
8086 if (r_timereport_active)
8087 R_TimeReport("coronas");
8090 // don't let sound skip if going slow
8091 if (r_refdef.scene.extraupdate)
8094 R_ResetViewRendering2D();
8097 static const unsigned short bboxelements[36] =
8107 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8110 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8112 RSurf_ActiveWorldEntity();
8114 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8115 GL_DepthMask(false);
8116 GL_DepthRange(0, 1);
8117 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8118 R_Mesh_ResetTextureState();
8120 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8121 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8122 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8123 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8124 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8125 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8126 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8127 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8128 R_FillColors(color4f, 8, cr, cg, cb, ca);
8129 if (r_refdef.fogenabled)
8131 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8133 f1 = RSurf_FogVertex(v);
8135 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8136 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8137 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8140 R_Mesh_VertexPointer(vertex3f, 0, 0);
8141 R_Mesh_ColorPointer(color4f, 0, 0);
8142 R_Mesh_ResetTextureState();
8143 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8144 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8147 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8151 prvm_edict_t *edict;
8152 prvm_prog_t *prog_save = prog;
8154 // this function draws bounding boxes of server entities
8158 GL_CullFace(GL_NONE);
8159 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8163 for (i = 0;i < numsurfaces;i++)
8165 edict = PRVM_EDICT_NUM(surfacelist[i]);
8166 switch ((int)edict->fields.server->solid)
8168 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
8169 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
8170 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
8171 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8172 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
8173 default: Vector4Set(color, 0, 0, 0, 0.50);break;
8175 color[3] *= r_showbboxes.value;
8176 color[3] = bound(0, color[3], 1);
8177 GL_DepthTest(!r_showdisabledepthtest.integer);
8178 GL_CullFace(r_refdef.view.cullface_front);
8179 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8185 static void R_DrawEntityBBoxes(void)
8188 prvm_edict_t *edict;
8190 prvm_prog_t *prog_save = prog;
8192 // this function draws bounding boxes of server entities
8198 for (i = 0;i < prog->num_edicts;i++)
8200 edict = PRVM_EDICT_NUM(i);
8201 if (edict->priv.server->free)
8203 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8204 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8206 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8208 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8209 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8215 static const int nomodelelement3i[24] =
8227 static const unsigned short nomodelelement3s[24] =
8239 static const float nomodelvertex3f[6*3] =
8249 static const float nomodelcolor4f[6*4] =
8251 0.0f, 0.0f, 0.5f, 1.0f,
8252 0.0f, 0.0f, 0.5f, 1.0f,
8253 0.0f, 0.5f, 0.0f, 1.0f,
8254 0.0f, 0.5f, 0.0f, 1.0f,
8255 0.5f, 0.0f, 0.0f, 1.0f,
8256 0.5f, 0.0f, 0.0f, 1.0f
8259 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8265 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);
8267 // this is only called once per entity so numsurfaces is always 1, and
8268 // surfacelist is always {0}, so this code does not handle batches
8270 if (rsurface.ent_flags & RENDER_ADDITIVE)
8272 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8273 GL_DepthMask(false);
8275 else if (rsurface.colormod[3] < 1)
8277 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8278 GL_DepthMask(false);
8282 GL_BlendFunc(GL_ONE, GL_ZERO);
8285 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8286 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8287 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8288 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8289 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8290 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8291 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8292 R_Mesh_ColorPointer(color4f, 0, 0);
8293 for (i = 0, c = color4f;i < 6;i++, c += 4)
8295 c[0] *= rsurface.colormod[0];
8296 c[1] *= rsurface.colormod[1];
8297 c[2] *= rsurface.colormod[2];
8298 c[3] *= rsurface.colormod[3];
8300 if (r_refdef.fogenabled)
8302 for (i = 0, c = color4f;i < 6;i++, c += 4)
8304 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8306 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8307 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8308 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8311 R_Mesh_ResetTextureState();
8312 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8315 void R_DrawNoModel(entity_render_t *ent)
8318 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8319 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8320 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8322 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8325 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8327 vec3_t right1, right2, diff, normal;
8329 VectorSubtract (org2, org1, normal);
8331 // calculate 'right' vector for start
8332 VectorSubtract (r_refdef.view.origin, org1, diff);
8333 CrossProduct (normal, diff, right1);
8334 VectorNormalize (right1);
8336 // calculate 'right' vector for end
8337 VectorSubtract (r_refdef.view.origin, org2, diff);
8338 CrossProduct (normal, diff, right2);
8339 VectorNormalize (right2);
8341 vert[ 0] = org1[0] + width * right1[0];
8342 vert[ 1] = org1[1] + width * right1[1];
8343 vert[ 2] = org1[2] + width * right1[2];
8344 vert[ 3] = org1[0] - width * right1[0];
8345 vert[ 4] = org1[1] - width * right1[1];
8346 vert[ 5] = org1[2] - width * right1[2];
8347 vert[ 6] = org2[0] - width * right2[0];
8348 vert[ 7] = org2[1] - width * right2[1];
8349 vert[ 8] = org2[2] - width * right2[2];
8350 vert[ 9] = org2[0] + width * right2[0];
8351 vert[10] = org2[1] + width * right2[1];
8352 vert[11] = org2[2] + width * right2[2];
8355 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)
8357 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8358 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8359 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8360 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8361 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8362 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8363 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8364 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8365 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8366 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8367 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8368 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8371 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8376 VectorSet(v, x, y, z);
8377 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8378 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8380 if (i == mesh->numvertices)
8382 if (mesh->numvertices < mesh->maxvertices)
8384 VectorCopy(v, vertex3f);
8385 mesh->numvertices++;
8387 return mesh->numvertices;
8393 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8397 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8398 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8399 e = mesh->element3i + mesh->numtriangles * 3;
8400 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8402 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8403 if (mesh->numtriangles < mesh->maxtriangles)
8408 mesh->numtriangles++;
8410 element[1] = element[2];
8414 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8418 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8419 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8420 e = mesh->element3i + mesh->numtriangles * 3;
8421 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8423 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8424 if (mesh->numtriangles < mesh->maxtriangles)
8429 mesh->numtriangles++;
8431 element[1] = element[2];
8435 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8436 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8438 int planenum, planenum2;
8441 mplane_t *plane, *plane2;
8443 double temppoints[2][256*3];
8444 // figure out how large a bounding box we need to properly compute this brush
8446 for (w = 0;w < numplanes;w++)
8447 maxdist = max(maxdist, fabs(planes[w].dist));
8448 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8449 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8450 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8454 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8455 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8457 if (planenum2 == planenum)
8459 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);
8462 if (tempnumpoints < 3)
8464 // generate elements forming a triangle fan for this polygon
8465 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8469 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)
8471 texturelayer_t *layer;
8472 layer = t->currentlayers + t->currentnumlayers++;
8474 layer->depthmask = depthmask;
8475 layer->blendfunc1 = blendfunc1;
8476 layer->blendfunc2 = blendfunc2;
8477 layer->texture = texture;
8478 layer->texmatrix = *matrix;
8479 layer->color[0] = r;
8480 layer->color[1] = g;
8481 layer->color[2] = b;
8482 layer->color[3] = a;
8485 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8488 index = parms[2] + r_refdef.scene.time * parms[3];
8489 index -= floor(index);
8493 case Q3WAVEFUNC_NONE:
8494 case Q3WAVEFUNC_NOISE:
8495 case Q3WAVEFUNC_COUNT:
8498 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8499 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8500 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8501 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8502 case Q3WAVEFUNC_TRIANGLE:
8504 f = index - floor(index);
8515 return (float)(parms[0] + parms[1] * f);
8518 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8523 matrix4x4_t matrix, temp;
8524 switch(tcmod->tcmod)
8528 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8529 matrix = r_waterscrollmatrix;
8531 matrix = identitymatrix;
8533 case Q3TCMOD_ENTITYTRANSLATE:
8534 // this is used in Q3 to allow the gamecode to control texcoord
8535 // scrolling on the entity, which is not supported in darkplaces yet.
8536 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8538 case Q3TCMOD_ROTATE:
8539 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8540 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8541 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8544 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8546 case Q3TCMOD_SCROLL:
8547 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8549 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8550 w = (int) tcmod->parms[0];
8551 h = (int) tcmod->parms[1];
8552 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8554 idx = (int) floor(f * w * h);
8555 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8557 case Q3TCMOD_STRETCH:
8558 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8559 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8561 case Q3TCMOD_TRANSFORM:
8562 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8563 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8564 VectorSet(tcmat + 6, 0 , 0 , 1);
8565 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8566 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8568 case Q3TCMOD_TURBULENT:
8569 // this is handled in the RSurf_PrepareVertices function
8570 matrix = identitymatrix;
8574 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8577 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8579 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8580 char name[MAX_QPATH];
8581 skinframe_t *skinframe;
8582 unsigned char pixels[296*194];
8583 strlcpy(cache->name, skinname, sizeof(cache->name));
8584 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8585 if (developer_loading.integer)
8586 Con_Printf("loading %s\n", name);
8587 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8588 if (!skinframe || !skinframe->base)
8591 fs_offset_t filesize;
8593 f = FS_LoadFile(name, tempmempool, true, &filesize);
8596 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8597 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8601 cache->skinframe = skinframe;
8604 texture_t *R_GetCurrentTexture(texture_t *t)
8607 const entity_render_t *ent = rsurface.entity;
8608 dp_model_t *model = ent->model;
8609 q3shaderinfo_layer_tcmod_t *tcmod;
8611 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8612 return t->currentframe;
8613 t->update_lastrenderframe = r_textureframe;
8614 t->update_lastrenderentity = (void *)ent;
8616 // switch to an alternate material if this is a q1bsp animated material
8618 texture_t *texture = t;
8619 int s = rsurface.ent_skinnum;
8620 if ((unsigned int)s >= (unsigned int)model->numskins)
8622 if (model->skinscenes)
8624 if (model->skinscenes[s].framecount > 1)
8625 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8627 s = model->skinscenes[s].firstframe;
8630 t = t + s * model->num_surfaces;
8633 // use an alternate animation if the entity's frame is not 0,
8634 // and only if the texture has an alternate animation
8635 if (rsurface.ent_alttextures && t->anim_total[1])
8636 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8638 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8640 texture->currentframe = t;
8643 // update currentskinframe to be a qw skin or animation frame
8644 if (rsurface.ent_qwskin >= 0)
8646 i = rsurface.ent_qwskin;
8647 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8649 r_qwskincache_size = cl.maxclients;
8651 Mem_Free(r_qwskincache);
8652 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8654 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8655 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8656 t->currentskinframe = r_qwskincache[i].skinframe;
8657 if (t->currentskinframe == NULL)
8658 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8660 else if (t->numskinframes >= 2)
8661 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8662 if (t->backgroundnumskinframes >= 2)
8663 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8665 t->currentmaterialflags = t->basematerialflags;
8666 t->currentalpha = rsurface.colormod[3];
8667 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8668 t->currentalpha *= r_wateralpha.value;
8669 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8670 t->currentalpha *= t->r_water_wateralpha;
8671 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8672 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8673 if (!(rsurface.ent_flags & RENDER_LIGHT))
8674 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8675 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8677 // pick a model lighting mode
8678 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8679 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8681 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8683 if (rsurface.ent_flags & RENDER_ADDITIVE)
8684 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8685 else if (t->currentalpha < 1)
8686 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8687 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8688 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8689 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8690 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8691 if (t->backgroundnumskinframes)
8692 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8693 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8695 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8696 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8699 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8700 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8701 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8703 // there is no tcmod
8704 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8706 t->currenttexmatrix = r_waterscrollmatrix;
8707 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8709 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8711 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8712 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8715 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8716 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8717 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8718 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8720 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8721 if (t->currentskinframe->qpixels)
8722 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8723 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8724 if (!t->basetexture)
8725 t->basetexture = r_texture_notexture;
8726 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8727 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8728 t->nmaptexture = t->currentskinframe->nmap;
8729 if (!t->nmaptexture)
8730 t->nmaptexture = r_texture_blanknormalmap;
8731 t->glosstexture = r_texture_black;
8732 t->glowtexture = t->currentskinframe->glow;
8733 t->fogtexture = t->currentskinframe->fog;
8734 if (t->backgroundnumskinframes)
8736 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8737 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8738 t->backgroundglosstexture = r_texture_black;
8739 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8740 if (!t->backgroundnmaptexture)
8741 t->backgroundnmaptexture = r_texture_blanknormalmap;
8745 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8746 t->backgroundnmaptexture = r_texture_blanknormalmap;
8747 t->backgroundglosstexture = r_texture_black;
8748 t->backgroundglowtexture = NULL;
8750 t->specularpower = r_shadow_glossexponent.value;
8751 // TODO: store reference values for these in the texture?
8752 t->specularscale = 0;
8753 if (r_shadow_gloss.integer > 0)
8755 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8757 if (r_shadow_glossintensity.value > 0)
8759 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8760 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8761 t->specularscale = r_shadow_glossintensity.value;
8764 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8766 t->glosstexture = r_texture_white;
8767 t->backgroundglosstexture = r_texture_white;
8768 t->specularscale = r_shadow_gloss2intensity.value;
8769 t->specularpower = r_shadow_gloss2exponent.value;
8772 t->specularscale *= t->specularscalemod;
8773 t->specularpower *= t->specularpowermod;
8775 // lightmaps mode looks bad with dlights using actual texturing, so turn
8776 // off the colormap and glossmap, but leave the normalmap on as it still
8777 // accurately represents the shading involved
8778 if (gl_lightmaps.integer)
8780 t->basetexture = r_texture_grey128;
8781 t->pantstexture = r_texture_black;
8782 t->shirttexture = r_texture_black;
8783 t->nmaptexture = r_texture_blanknormalmap;
8784 t->glosstexture = r_texture_black;
8785 t->glowtexture = NULL;
8786 t->fogtexture = NULL;
8787 t->backgroundbasetexture = NULL;
8788 t->backgroundnmaptexture = r_texture_blanknormalmap;
8789 t->backgroundglosstexture = r_texture_black;
8790 t->backgroundglowtexture = NULL;
8791 t->specularscale = 0;
8792 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8795 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8796 VectorClear(t->dlightcolor);
8797 t->currentnumlayers = 0;
8798 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8800 int blendfunc1, blendfunc2;
8802 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8804 blendfunc1 = GL_SRC_ALPHA;
8805 blendfunc2 = GL_ONE;
8807 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8809 blendfunc1 = GL_SRC_ALPHA;
8810 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8812 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8814 blendfunc1 = t->customblendfunc[0];
8815 blendfunc2 = t->customblendfunc[1];
8819 blendfunc1 = GL_ONE;
8820 blendfunc2 = GL_ZERO;
8822 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8823 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8825 // fullbright is not affected by r_refdef.lightmapintensity
8826 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]);
8827 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8828 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]);
8829 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8830 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]);
8834 vec3_t ambientcolor;
8836 // set the color tint used for lights affecting this surface
8837 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8839 // q3bsp has no lightmap updates, so the lightstylevalue that
8840 // would normally be baked into the lightmap must be
8841 // applied to the color
8842 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8843 if (model->type == mod_brushq3)
8844 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8845 colorscale *= r_refdef.lightmapintensity;
8846 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8847 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8848 // basic lit geometry
8849 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]);
8850 // add pants/shirt if needed
8851 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8852 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]);
8853 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8854 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]);
8855 // now add ambient passes if needed
8856 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8858 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]);
8859 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8860 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]);
8861 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8862 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]);
8865 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8866 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]);
8867 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8869 // if this is opaque use alpha blend which will darken the earlier
8872 // if this is an alpha blended material, all the earlier passes
8873 // were darkened by fog already, so we only need to add the fog
8874 // color ontop through the fog mask texture
8876 // if this is an additive blended material, all the earlier passes
8877 // were darkened by fog already, and we should not add fog color
8878 // (because the background was not darkened, there is no fog color
8879 // that was lost behind it).
8880 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]);
8884 return t->currentframe;
8887 rsurfacestate_t rsurface;
8889 void R_Mesh_ResizeArrays(int newvertices)
8892 if (rsurface.array_size >= newvertices)
8894 if (rsurface.array_modelvertex3f)
8895 Mem_Free(rsurface.array_modelvertex3f);
8896 rsurface.array_size = (newvertices + 1023) & ~1023;
8897 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8898 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
8899 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
8900 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
8901 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
8902 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
8903 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8904 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8905 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
8906 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
8907 rsurface.array_color4f = base + rsurface.array_size * 27;
8908 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8911 void RSurf_ActiveWorldEntity(void)
8913 dp_model_t *model = r_refdef.scene.worldmodel;
8914 //if (rsurface.entity == r_refdef.scene.worldentity)
8916 rsurface.entity = r_refdef.scene.worldentity;
8917 rsurface.skeleton = NULL;
8918 rsurface.ent_skinnum = 0;
8919 rsurface.ent_qwskin = -1;
8920 rsurface.ent_shadertime = 0;
8921 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8922 if (rsurface.array_size < model->surfmesh.num_vertices)
8923 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8924 rsurface.matrix = identitymatrix;
8925 rsurface.inversematrix = identitymatrix;
8926 rsurface.matrixscale = 1;
8927 rsurface.inversematrixscale = 1;
8928 R_EntityMatrix(&identitymatrix);
8929 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8930 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8931 rsurface.fograngerecip = r_refdef.fograngerecip;
8932 rsurface.fogheightfade = r_refdef.fogheightfade;
8933 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8934 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8935 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8936 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8937 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8938 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8939 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8940 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8941 rsurface.colormod[3] = 1;
8942 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);
8943 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8944 rsurface.frameblend[0].lerp = 1;
8945 rsurface.ent_alttextures = false;
8946 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8947 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8948 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8949 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8950 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8951 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8952 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8953 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8954 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8955 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8956 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8957 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8958 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8959 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8960 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8961 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8962 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8963 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8964 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8965 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8966 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8967 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8968 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8969 rsurface.modelelement3i = model->surfmesh.data_element3i;
8970 rsurface.modelelement3s = model->surfmesh.data_element3s;
8971 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8972 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8973 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8974 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8975 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8976 rsurface.modelsurfaces = model->data_surfaces;
8977 rsurface.generatedvertex = false;
8978 rsurface.vertex3f = rsurface.modelvertex3f;
8979 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8980 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8981 rsurface.svector3f = rsurface.modelsvector3f;
8982 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8983 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8984 rsurface.tvector3f = rsurface.modeltvector3f;
8985 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8986 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8987 rsurface.normal3f = rsurface.modelnormal3f;
8988 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8989 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8990 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8993 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8995 dp_model_t *model = ent->model;
8996 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8998 rsurface.entity = (entity_render_t *)ent;
8999 rsurface.skeleton = ent->skeleton;
9000 rsurface.ent_skinnum = ent->skinnum;
9001 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;
9002 rsurface.ent_shadertime = ent->shadertime;
9003 rsurface.ent_flags = ent->flags;
9004 if (rsurface.array_size < model->surfmesh.num_vertices)
9005 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9006 rsurface.matrix = ent->matrix;
9007 rsurface.inversematrix = ent->inversematrix;
9008 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9009 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9010 R_EntityMatrix(&rsurface.matrix);
9011 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9012 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9013 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9014 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9015 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9016 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9017 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9018 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9019 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9020 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9021 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9022 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9023 rsurface.colormod[3] = ent->alpha;
9024 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9025 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9026 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9027 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9028 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9029 if (ent->model->brush.submodel && !prepass)
9031 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9032 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9034 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9036 if (ent->animcache_vertex3f && !r_framedata_failed)
9038 rsurface.modelvertex3f = ent->animcache_vertex3f;
9039 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9040 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9041 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9043 else if (wanttangents)
9045 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9046 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9047 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9048 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9049 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9051 else if (wantnormals)
9053 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9054 rsurface.modelsvector3f = NULL;
9055 rsurface.modeltvector3f = NULL;
9056 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9057 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9061 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9062 rsurface.modelsvector3f = NULL;
9063 rsurface.modeltvector3f = NULL;
9064 rsurface.modelnormal3f = NULL;
9065 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9067 rsurface.modelvertex3f_bufferobject = 0;
9068 rsurface.modelvertex3f_bufferoffset = 0;
9069 rsurface.modelsvector3f_bufferobject = 0;
9070 rsurface.modelsvector3f_bufferoffset = 0;
9071 rsurface.modeltvector3f_bufferobject = 0;
9072 rsurface.modeltvector3f_bufferoffset = 0;
9073 rsurface.modelnormal3f_bufferobject = 0;
9074 rsurface.modelnormal3f_bufferoffset = 0;
9075 rsurface.generatedvertex = true;
9079 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9080 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9081 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9082 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9083 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9084 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9085 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9086 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9087 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9088 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9089 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9090 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9091 rsurface.generatedvertex = false;
9093 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9094 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9095 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9096 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9097 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9098 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9099 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9100 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9101 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9102 rsurface.modelelement3i = model->surfmesh.data_element3i;
9103 rsurface.modelelement3s = model->surfmesh.data_element3s;
9104 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9105 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9106 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9107 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9108 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9109 rsurface.modelsurfaces = model->data_surfaces;
9110 rsurface.vertex3f = rsurface.modelvertex3f;
9111 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9112 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9113 rsurface.svector3f = rsurface.modelsvector3f;
9114 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9115 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9116 rsurface.tvector3f = rsurface.modeltvector3f;
9117 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9118 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9119 rsurface.normal3f = rsurface.modelnormal3f;
9120 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9121 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9122 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9125 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)
9127 rsurface.entity = r_refdef.scene.worldentity;
9128 rsurface.skeleton = NULL;
9129 rsurface.ent_skinnum = 0;
9130 rsurface.ent_qwskin = -1;
9131 rsurface.ent_shadertime = shadertime;
9132 rsurface.ent_flags = entflags;
9133 rsurface.modelnum_vertices = numvertices;
9134 rsurface.modelnum_triangles = numtriangles;
9135 if (rsurface.array_size < rsurface.modelnum_vertices)
9136 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9137 rsurface.matrix = *matrix;
9138 rsurface.inversematrix = *inversematrix;
9139 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9140 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9141 R_EntityMatrix(&rsurface.matrix);
9142 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9143 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9144 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9145 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9146 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9147 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9148 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9149 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9150 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9151 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9152 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9153 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9154 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);
9155 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9156 rsurface.frameblend[0].lerp = 1;
9157 rsurface.ent_alttextures = false;
9158 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9159 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9162 rsurface.modelvertex3f = vertex3f;
9163 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9164 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9165 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9167 else if (wantnormals)
9169 rsurface.modelvertex3f = vertex3f;
9170 rsurface.modelsvector3f = NULL;
9171 rsurface.modeltvector3f = NULL;
9172 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9176 rsurface.modelvertex3f = vertex3f;
9177 rsurface.modelsvector3f = NULL;
9178 rsurface.modeltvector3f = NULL;
9179 rsurface.modelnormal3f = NULL;
9181 rsurface.modelvertex3f_bufferobject = 0;
9182 rsurface.modelvertex3f_bufferoffset = 0;
9183 rsurface.modelsvector3f_bufferobject = 0;
9184 rsurface.modelsvector3f_bufferoffset = 0;
9185 rsurface.modeltvector3f_bufferobject = 0;
9186 rsurface.modeltvector3f_bufferoffset = 0;
9187 rsurface.modelnormal3f_bufferobject = 0;
9188 rsurface.modelnormal3f_bufferoffset = 0;
9189 rsurface.generatedvertex = true;
9190 rsurface.modellightmapcolor4f = color4f;
9191 rsurface.modellightmapcolor4f_bufferobject = 0;
9192 rsurface.modellightmapcolor4f_bufferoffset = 0;
9193 rsurface.modeltexcoordtexture2f = texcoord2f;
9194 rsurface.modeltexcoordtexture2f_bufferobject = 0;
9195 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9196 rsurface.modeltexcoordlightmap2f = NULL;
9197 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9198 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9199 rsurface.modelelement3i = element3i;
9200 rsurface.modelelement3s = element3s;
9201 rsurface.modelelement3i_bufferobject = 0;
9202 rsurface.modelelement3s_bufferobject = 0;
9203 rsurface.modellightmapoffsets = NULL;
9204 rsurface.modelsurfaces = NULL;
9205 rsurface.vertex3f = rsurface.modelvertex3f;
9206 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9207 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9208 rsurface.svector3f = rsurface.modelsvector3f;
9209 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9210 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9211 rsurface.tvector3f = rsurface.modeltvector3f;
9212 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9213 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9214 rsurface.normal3f = rsurface.modelnormal3f;
9215 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9216 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9217 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9219 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9221 if ((wantnormals || wanttangents) && !normal3f)
9222 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9223 if (wanttangents && !svector3f)
9224 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);
9228 float RSurf_FogPoint(const float *v)
9230 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9231 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9232 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9233 float FogHeightFade = r_refdef.fogheightfade;
9235 unsigned int fogmasktableindex;
9236 if (r_refdef.fogplaneviewabove)
9237 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9239 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9240 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9241 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9244 float RSurf_FogVertex(const float *v)
9246 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9247 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9248 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9249 float FogHeightFade = rsurface.fogheightfade;
9251 unsigned int fogmasktableindex;
9252 if (r_refdef.fogplaneviewabove)
9253 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9255 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9256 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9257 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9260 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9261 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9264 int texturesurfaceindex;
9269 const float *v1, *in_tc;
9271 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9273 q3shaderinfo_deform_t *deform;
9274 // 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
9275 if (rsurface.generatedvertex)
9277 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9278 generatenormals = true;
9279 for (i = 0;i < Q3MAXDEFORMS;i++)
9281 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9283 generatetangents = true;
9284 generatenormals = true;
9286 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9287 generatenormals = true;
9289 if (generatenormals && !rsurface.modelnormal3f)
9291 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9292 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9293 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9294 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9296 if (generatetangents && !rsurface.modelsvector3f)
9298 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9299 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9300 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9301 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9302 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9303 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9304 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);
9307 rsurface.vertex3f = rsurface.modelvertex3f;
9308 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9309 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9310 rsurface.svector3f = rsurface.modelsvector3f;
9311 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9312 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9313 rsurface.tvector3f = rsurface.modeltvector3f;
9314 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9315 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9316 rsurface.normal3f = rsurface.modelnormal3f;
9317 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9318 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9319 // if vertices are deformed (sprite flares and things in maps, possibly
9320 // water waves, bulges and other deformations), generate them into
9321 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9322 // (may be static model data or generated data for an animated model, or
9323 // the previous deform pass)
9324 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9326 switch (deform->deform)
9329 case Q3DEFORM_PROJECTIONSHADOW:
9330 case Q3DEFORM_TEXT0:
9331 case Q3DEFORM_TEXT1:
9332 case Q3DEFORM_TEXT2:
9333 case Q3DEFORM_TEXT3:
9334 case Q3DEFORM_TEXT4:
9335 case Q3DEFORM_TEXT5:
9336 case Q3DEFORM_TEXT6:
9337 case Q3DEFORM_TEXT7:
9340 case Q3DEFORM_AUTOSPRITE:
9341 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9342 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9343 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9344 VectorNormalize(newforward);
9345 VectorNormalize(newright);
9346 VectorNormalize(newup);
9347 // make deformed versions of only the model vertices used by the specified surfaces
9348 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9350 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9351 // a single autosprite surface can contain multiple sprites...
9352 for (j = 0;j < surface->num_vertices - 3;j += 4)
9354 VectorClear(center);
9355 for (i = 0;i < 4;i++)
9356 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9357 VectorScale(center, 0.25f, center);
9358 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9359 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9360 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9361 for (i = 0;i < 4;i++)
9363 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9364 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9367 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);
9368 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);
9370 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9371 rsurface.vertex3f_bufferobject = 0;
9372 rsurface.vertex3f_bufferoffset = 0;
9373 rsurface.svector3f = rsurface.array_deformedsvector3f;
9374 rsurface.svector3f_bufferobject = 0;
9375 rsurface.svector3f_bufferoffset = 0;
9376 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9377 rsurface.tvector3f_bufferobject = 0;
9378 rsurface.tvector3f_bufferoffset = 0;
9379 rsurface.normal3f = rsurface.array_deformednormal3f;
9380 rsurface.normal3f_bufferobject = 0;
9381 rsurface.normal3f_bufferoffset = 0;
9383 case Q3DEFORM_AUTOSPRITE2:
9384 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9385 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9386 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9387 VectorNormalize(newforward);
9388 VectorNormalize(newright);
9389 VectorNormalize(newup);
9390 // make deformed versions of only the model vertices used by the specified surfaces
9391 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9393 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9394 const float *v1, *v2;
9404 memset(shortest, 0, sizeof(shortest));
9405 // a single autosprite surface can contain multiple sprites...
9406 for (j = 0;j < surface->num_vertices - 3;j += 4)
9408 VectorClear(center);
9409 for (i = 0;i < 4;i++)
9410 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9411 VectorScale(center, 0.25f, center);
9412 // find the two shortest edges, then use them to define the
9413 // axis vectors for rotating around the central axis
9414 for (i = 0;i < 6;i++)
9416 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9417 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9419 Debug_PolygonBegin(NULL, 0);
9420 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9421 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);
9422 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9425 l = VectorDistance2(v1, v2);
9426 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9428 l += (1.0f / 1024.0f);
9429 if (shortest[0].length2 > l || i == 0)
9431 shortest[1] = shortest[0];
9432 shortest[0].length2 = l;
9433 shortest[0].v1 = v1;
9434 shortest[0].v2 = v2;
9436 else if (shortest[1].length2 > l || i == 1)
9438 shortest[1].length2 = l;
9439 shortest[1].v1 = v1;
9440 shortest[1].v2 = v2;
9443 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9444 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9446 Debug_PolygonBegin(NULL, 0);
9447 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9448 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);
9449 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9452 // this calculates the right vector from the shortest edge
9453 // and the up vector from the edge midpoints
9454 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9455 VectorNormalize(right);
9456 VectorSubtract(end, start, up);
9457 VectorNormalize(up);
9458 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9459 VectorSubtract(rsurface.localvieworigin, center, forward);
9460 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9461 VectorNegate(forward, forward);
9462 VectorReflect(forward, 0, up, forward);
9463 VectorNormalize(forward);
9464 CrossProduct(up, forward, newright);
9465 VectorNormalize(newright);
9467 Debug_PolygonBegin(NULL, 0);
9468 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);
9469 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9470 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9474 Debug_PolygonBegin(NULL, 0);
9475 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9476 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9477 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9480 // rotate the quad around the up axis vector, this is made
9481 // especially easy by the fact we know the quad is flat,
9482 // so we only have to subtract the center position and
9483 // measure distance along the right vector, and then
9484 // multiply that by the newright vector and add back the
9486 // we also need to subtract the old position to undo the
9487 // displacement from the center, which we do with a
9488 // DotProduct, the subtraction/addition of center is also
9489 // optimized into DotProducts here
9490 l = DotProduct(right, center);
9491 for (i = 0;i < 4;i++)
9493 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9494 f = DotProduct(right, v1) - l;
9495 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9498 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);
9499 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);
9501 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9502 rsurface.vertex3f_bufferobject = 0;
9503 rsurface.vertex3f_bufferoffset = 0;
9504 rsurface.svector3f = rsurface.array_deformedsvector3f;
9505 rsurface.svector3f_bufferobject = 0;
9506 rsurface.svector3f_bufferoffset = 0;
9507 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9508 rsurface.tvector3f_bufferobject = 0;
9509 rsurface.tvector3f_bufferoffset = 0;
9510 rsurface.normal3f = rsurface.array_deformednormal3f;
9511 rsurface.normal3f_bufferobject = 0;
9512 rsurface.normal3f_bufferoffset = 0;
9514 case Q3DEFORM_NORMAL:
9515 // deform the normals to make reflections wavey
9516 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9518 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9519 for (j = 0;j < surface->num_vertices;j++)
9522 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9523 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9524 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9525 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9526 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9527 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9528 VectorNormalize(normal);
9530 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);
9532 rsurface.svector3f = rsurface.array_deformedsvector3f;
9533 rsurface.svector3f_bufferobject = 0;
9534 rsurface.svector3f_bufferoffset = 0;
9535 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9536 rsurface.tvector3f_bufferobject = 0;
9537 rsurface.tvector3f_bufferoffset = 0;
9538 rsurface.normal3f = rsurface.array_deformednormal3f;
9539 rsurface.normal3f_bufferobject = 0;
9540 rsurface.normal3f_bufferoffset = 0;
9543 // deform vertex array to make wavey water and flags and such
9544 waveparms[0] = deform->waveparms[0];
9545 waveparms[1] = deform->waveparms[1];
9546 waveparms[2] = deform->waveparms[2];
9547 waveparms[3] = deform->waveparms[3];
9548 // this is how a divisor of vertex influence on deformation
9549 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9550 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9551 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9553 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9554 for (j = 0;j < surface->num_vertices;j++)
9556 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9557 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9558 // if the wavefunc depends on time, evaluate it per-vertex
9561 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9562 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9564 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9567 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9568 rsurface.vertex3f_bufferobject = 0;
9569 rsurface.vertex3f_bufferoffset = 0;
9571 case Q3DEFORM_BULGE:
9572 // deform vertex array to make the surface have moving bulges
9573 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9575 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9576 for (j = 0;j < surface->num_vertices;j++)
9578 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9579 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9582 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9583 rsurface.vertex3f_bufferobject = 0;
9584 rsurface.vertex3f_bufferoffset = 0;
9587 // deform vertex array
9588 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9589 VectorScale(deform->parms, scale, waveparms);
9590 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9592 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9593 for (j = 0;j < surface->num_vertices;j++)
9594 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9596 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9597 rsurface.vertex3f_bufferobject = 0;
9598 rsurface.vertex3f_bufferoffset = 0;
9602 // generate texcoords based on the chosen texcoord source
9603 switch(rsurface.texture->tcgen.tcgen)
9606 case Q3TCGEN_TEXTURE:
9607 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9608 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
9609 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9611 case Q3TCGEN_LIGHTMAP:
9612 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
9613 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9614 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9616 case Q3TCGEN_VECTOR:
9617 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9619 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9620 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)
9622 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9623 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9626 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9627 rsurface.texcoordtexture2f_bufferobject = 0;
9628 rsurface.texcoordtexture2f_bufferoffset = 0;
9630 case Q3TCGEN_ENVIRONMENT:
9631 // make environment reflections using a spheremap
9632 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9634 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9635 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9636 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9637 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9638 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9640 // identical to Q3A's method, but executed in worldspace so
9641 // carried models can be shiny too
9643 float viewer[3], d, reflected[3], worldreflected[3];
9645 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9646 // VectorNormalize(viewer);
9648 d = DotProduct(normal, viewer);
9650 reflected[0] = normal[0]*2*d - viewer[0];
9651 reflected[1] = normal[1]*2*d - viewer[1];
9652 reflected[2] = normal[2]*2*d - viewer[2];
9653 // note: this is proportinal to viewer, so we can normalize later
9655 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9656 VectorNormalize(worldreflected);
9658 // note: this sphere map only uses world x and z!
9659 // so positive and negative y will LOOK THE SAME.
9660 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9661 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9664 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9665 rsurface.texcoordtexture2f_bufferobject = 0;
9666 rsurface.texcoordtexture2f_bufferoffset = 0;
9669 // the only tcmod that needs software vertex processing is turbulent, so
9670 // check for it here and apply the changes if needed
9671 // and we only support that as the first one
9672 // (handling a mixture of turbulent and other tcmods would be problematic
9673 // without punting it entirely to a software path)
9674 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9676 amplitude = rsurface.texture->tcmods[0].parms[1];
9677 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9678 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9680 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9681 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)
9683 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9684 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9687 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9688 rsurface.texcoordtexture2f_bufferobject = 0;
9689 rsurface.texcoordtexture2f_bufferoffset = 0;
9691 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9692 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9693 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9694 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9697 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9700 const msurface_t *surface = texturesurfacelist[0];
9701 const msurface_t *surface2;
9706 // TODO: lock all array ranges before render, rather than on each surface
9707 if (texturenumsurfaces == 1)
9708 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);
9709 else if (r_batchmode.integer == 2)
9711 #define MAXBATCHTRIANGLES 4096
9712 int batchtriangles = 0;
9713 static int batchelements[MAXBATCHTRIANGLES*3];
9714 for (i = 0;i < texturenumsurfaces;i = j)
9716 surface = texturesurfacelist[i];
9718 if (surface->num_triangles > MAXBATCHTRIANGLES)
9720 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);
9723 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9724 batchtriangles = surface->num_triangles;
9725 firstvertex = surface->num_firstvertex;
9726 endvertex = surface->num_firstvertex + surface->num_vertices;
9727 for (;j < texturenumsurfaces;j++)
9729 surface2 = texturesurfacelist[j];
9730 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9732 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9733 batchtriangles += surface2->num_triangles;
9734 firstvertex = min(firstvertex, surface2->num_firstvertex);
9735 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9737 surface2 = texturesurfacelist[j-1];
9738 numvertices = endvertex - firstvertex;
9739 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9742 else if (r_batchmode.integer == 1)
9744 for (i = 0;i < texturenumsurfaces;i = j)
9746 surface = texturesurfacelist[i];
9747 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9748 if (texturesurfacelist[j] != surface2)
9750 surface2 = texturesurfacelist[j-1];
9751 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9752 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9753 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9758 for (i = 0;i < texturenumsurfaces;i++)
9760 surface = texturesurfacelist[i];
9761 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);
9766 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9768 switch(vid.renderpath)
9770 case RENDERPATH_CGGL:
9772 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9773 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9776 case RENDERPATH_GL20:
9777 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9778 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9780 case RENDERPATH_GL13:
9781 case RENDERPATH_GL11:
9782 R_Mesh_TexBind(0, surface->lightmaptexture);
9787 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9789 // pick the closest matching water plane and bind textures
9790 int planeindex, vertexindex;
9794 r_waterstate_waterplane_t *p, *bestp;
9797 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9800 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9802 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9803 d += fabs(PlaneDiff(vert, &p->plane));
9805 if (bestd > d || !bestp)
9811 switch(vid.renderpath)
9813 case RENDERPATH_CGGL:
9815 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9816 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9819 case RENDERPATH_GL20:
9820 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9821 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9823 case RENDERPATH_GL13:
9824 case RENDERPATH_GL11:
9829 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9832 const msurface_t *surface;
9833 if (r_waterstate.renderingscene)
9835 for (i = 0;i < texturenumsurfaces;i++)
9837 surface = texturesurfacelist[i];
9838 RSurf_BindLightmapForSurface(surface);
9839 RSurf_BindReflectionForSurface(surface);
9840 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);
9844 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9848 const msurface_t *surface = texturesurfacelist[0];
9849 const msurface_t *surface2;
9854 if (texturenumsurfaces == 1)
9856 RSurf_BindLightmapForSurface(surface);
9857 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);
9859 else if (r_batchmode.integer == 2)
9861 #define MAXBATCHTRIANGLES 4096
9862 int batchtriangles = 0;
9863 static int batchelements[MAXBATCHTRIANGLES*3];
9864 for (i = 0;i < texturenumsurfaces;i = j)
9866 surface = texturesurfacelist[i];
9867 RSurf_BindLightmapForSurface(surface);
9869 if (surface->num_triangles > MAXBATCHTRIANGLES)
9871 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);
9874 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9875 batchtriangles = surface->num_triangles;
9876 firstvertex = surface->num_firstvertex;
9877 endvertex = surface->num_firstvertex + surface->num_vertices;
9878 for (;j < texturenumsurfaces;j++)
9880 surface2 = texturesurfacelist[j];
9881 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9883 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9884 batchtriangles += surface2->num_triangles;
9885 firstvertex = min(firstvertex, surface2->num_firstvertex);
9886 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9888 surface2 = texturesurfacelist[j-1];
9889 numvertices = endvertex - firstvertex;
9890 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9893 else if (r_batchmode.integer == 1)
9896 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9897 for (i = 0;i < texturenumsurfaces;i = j)
9899 surface = texturesurfacelist[i];
9900 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9901 if (texturesurfacelist[j] != surface2)
9903 Con_Printf(" %i", j - i);
9906 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9908 for (i = 0;i < texturenumsurfaces;i = j)
9910 surface = texturesurfacelist[i];
9911 RSurf_BindLightmapForSurface(surface);
9912 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9913 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9916 Con_Printf(" %i", j - i);
9918 surface2 = texturesurfacelist[j-1];
9919 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9920 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9921 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9929 for (i = 0;i < texturenumsurfaces;i++)
9931 surface = texturesurfacelist[i];
9932 RSurf_BindLightmapForSurface(surface);
9933 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);
9938 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9941 int texturesurfaceindex;
9942 if (r_showsurfaces.integer == 2)
9944 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9946 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9947 for (j = 0;j < surface->num_triangles;j++)
9949 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9950 GL_Color(f, f, f, 1);
9951 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9957 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9959 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9960 int k = (int)(((size_t)surface) / sizeof(msurface_t));
9961 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);
9962 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);
9967 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9969 int texturesurfaceindex;
9973 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9975 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9976 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)
9984 rsurface.lightmapcolor4f = rsurface.array_color4f;
9985 rsurface.lightmapcolor4f_bufferobject = 0;
9986 rsurface.lightmapcolor4f_bufferoffset = 0;
9989 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9991 int texturesurfaceindex;
9997 if (rsurface.lightmapcolor4f)
9999 // generate color arrays for the surfaces in this list
10000 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10002 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10003 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)
10005 f = RSurf_FogVertex(v);
10015 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10017 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10018 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)
10020 f = RSurf_FogVertex(v);
10028 rsurface.lightmapcolor4f = rsurface.array_color4f;
10029 rsurface.lightmapcolor4f_bufferobject = 0;
10030 rsurface.lightmapcolor4f_bufferoffset = 0;
10033 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10035 int texturesurfaceindex;
10041 if (!rsurface.lightmapcolor4f)
10043 // generate color arrays for the surfaces in this list
10044 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10046 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10047 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)
10049 f = RSurf_FogVertex(v);
10050 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10051 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10052 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10056 rsurface.lightmapcolor4f = rsurface.array_color4f;
10057 rsurface.lightmapcolor4f_bufferobject = 0;
10058 rsurface.lightmapcolor4f_bufferoffset = 0;
10061 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10063 int texturesurfaceindex;
10067 if (!rsurface.lightmapcolor4f)
10069 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10071 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10072 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)
10080 rsurface.lightmapcolor4f = rsurface.array_color4f;
10081 rsurface.lightmapcolor4f_bufferobject = 0;
10082 rsurface.lightmapcolor4f_bufferoffset = 0;
10085 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10087 int texturesurfaceindex;
10091 if (!rsurface.lightmapcolor4f)
10093 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10095 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10096 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)
10098 c2[0] = c[0] + r_refdef.scene.ambient;
10099 c2[1] = c[1] + r_refdef.scene.ambient;
10100 c2[2] = c[2] + r_refdef.scene.ambient;
10104 rsurface.lightmapcolor4f = rsurface.array_color4f;
10105 rsurface.lightmapcolor4f_bufferobject = 0;
10106 rsurface.lightmapcolor4f_bufferoffset = 0;
10109 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10112 rsurface.lightmapcolor4f = NULL;
10113 rsurface.lightmapcolor4f_bufferobject = 0;
10114 rsurface.lightmapcolor4f_bufferoffset = 0;
10115 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10116 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10117 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10118 GL_Color(r, g, b, a);
10119 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10122 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10124 // TODO: optimize applyfog && applycolor case
10125 // just apply fog if necessary, and tint the fog color array if necessary
10126 rsurface.lightmapcolor4f = NULL;
10127 rsurface.lightmapcolor4f_bufferobject = 0;
10128 rsurface.lightmapcolor4f_bufferoffset = 0;
10129 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10130 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10131 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10132 GL_Color(r, g, b, a);
10133 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10136 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10138 int texturesurfaceindex;
10142 if (texturesurfacelist[0]->lightmapinfo)
10144 // generate color arrays for the surfaces in this list
10145 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10147 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10148 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10150 if (surface->lightmapinfo->samples)
10152 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10153 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10154 VectorScale(lm, scale, c);
10155 if (surface->lightmapinfo->styles[1] != 255)
10157 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10159 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10160 VectorMA(c, scale, lm, c);
10161 if (surface->lightmapinfo->styles[2] != 255)
10164 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10165 VectorMA(c, scale, lm, c);
10166 if (surface->lightmapinfo->styles[3] != 255)
10169 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10170 VectorMA(c, scale, lm, c);
10180 rsurface.lightmapcolor4f = rsurface.array_color4f;
10181 rsurface.lightmapcolor4f_bufferobject = 0;
10182 rsurface.lightmapcolor4f_bufferoffset = 0;
10186 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10187 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10188 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10190 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10191 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10192 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10193 GL_Color(r, g, b, a);
10194 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10197 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10199 int texturesurfaceindex;
10206 vec3_t ambientcolor;
10207 vec3_t diffusecolor;
10211 VectorCopy(rsurface.modellight_lightdir, lightdir);
10212 f = 0.5f * r_refdef.lightmapintensity;
10213 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10214 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10215 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10216 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10217 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10218 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10220 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10222 // generate color arrays for the surfaces in this list
10223 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10225 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10226 int numverts = surface->num_vertices;
10227 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10228 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10229 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10230 // q3-style directional shading
10231 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10233 if ((f = DotProduct(n, lightdir)) > 0)
10234 VectorMA(ambientcolor, f, diffusecolor, c);
10236 VectorCopy(ambientcolor, c);
10244 rsurface.lightmapcolor4f = rsurface.array_color4f;
10245 rsurface.lightmapcolor4f_bufferobject = 0;
10246 rsurface.lightmapcolor4f_bufferoffset = 0;
10247 *applycolor = false;
10251 *r = ambientcolor[0];
10252 *g = ambientcolor[1];
10253 *b = ambientcolor[2];
10254 rsurface.lightmapcolor4f = NULL;
10255 rsurface.lightmapcolor4f_bufferobject = 0;
10256 rsurface.lightmapcolor4f_bufferoffset = 0;
10260 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10262 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10263 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10264 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10265 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10266 GL_Color(r, g, b, a);
10267 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10270 void RSurf_SetupDepthAndCulling(void)
10272 // submodels are biased to avoid z-fighting with world surfaces that they
10273 // may be exactly overlapping (avoids z-fighting artifacts on certain
10274 // doors and things in Quake maps)
10275 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10276 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10277 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10278 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10281 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10283 // transparent sky would be ridiculous
10284 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10286 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10287 skyrenderlater = true;
10288 RSurf_SetupDepthAndCulling();
10289 GL_DepthMask(true);
10290 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10291 // skymasking on them, and Quake3 never did sky masking (unlike
10292 // software Quake and software Quake2), so disable the sky masking
10293 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10294 // and skymasking also looks very bad when noclipping outside the
10295 // level, so don't use it then either.
10296 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10298 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10299 R_Mesh_ColorPointer(NULL, 0, 0);
10300 R_Mesh_ResetTextureState();
10301 if (skyrendermasked)
10303 R_SetupShader_DepthOrShadow();
10304 // depth-only (masking)
10305 GL_ColorMask(0,0,0,0);
10306 // just to make sure that braindead drivers don't draw
10307 // anything despite that colormask...
10308 GL_BlendFunc(GL_ZERO, GL_ONE);
10312 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10314 GL_BlendFunc(GL_ONE, GL_ZERO);
10316 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10317 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10318 if (skyrendermasked)
10319 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10321 R_Mesh_ResetTextureState();
10322 GL_Color(1, 1, 1, 1);
10325 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10326 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10327 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10329 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10332 // render screenspace normalmap to texture
10333 GL_DepthMask(true);
10334 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10335 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10337 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10339 // render water or distortion background, then blend surface on top
10340 GL_DepthMask(true);
10341 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10342 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10343 GL_DepthMask(false);
10344 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10345 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10349 // render surface normally
10350 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10351 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10352 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10353 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10354 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10355 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10357 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10361 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10363 // OpenGL 1.3 path - anything not completely ancient
10364 int texturesurfaceindex;
10365 qboolean applycolor;
10368 const texturelayer_t *layer;
10369 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10371 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10374 int layertexrgbscale;
10375 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10377 if (layerindex == 0)
10378 GL_AlphaTest(true);
10381 GL_AlphaTest(false);
10382 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10385 GL_DepthMask(layer->depthmask && writedepth);
10386 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10387 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10389 layertexrgbscale = 4;
10390 VectorScale(layer->color, 0.25f, layercolor);
10392 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10394 layertexrgbscale = 2;
10395 VectorScale(layer->color, 0.5f, layercolor);
10399 layertexrgbscale = 1;
10400 VectorScale(layer->color, 1.0f, layercolor);
10402 layercolor[3] = layer->color[3];
10403 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10404 R_Mesh_ColorPointer(NULL, 0, 0);
10405 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10406 switch (layer->type)
10408 case TEXTURELAYERTYPE_LITTEXTURE:
10409 // single-pass lightmapped texture with 2x rgbscale
10410 R_Mesh_TexBind(0, r_texture_white);
10411 R_Mesh_TexMatrix(0, NULL);
10412 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10413 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10414 R_Mesh_TexBind(1, layer->texture);
10415 R_Mesh_TexMatrix(1, &layer->texmatrix);
10416 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10417 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10418 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10419 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10420 else if (rsurface.uselightmaptexture)
10421 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10423 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10425 case TEXTURELAYERTYPE_TEXTURE:
10426 // singletexture unlit texture with transparency support
10427 R_Mesh_TexBind(0, layer->texture);
10428 R_Mesh_TexMatrix(0, &layer->texmatrix);
10429 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10430 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10431 R_Mesh_TexBind(1, 0);
10432 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10433 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10435 case TEXTURELAYERTYPE_FOG:
10436 // singletexture fogging
10437 if (layer->texture)
10439 R_Mesh_TexBind(0, layer->texture);
10440 R_Mesh_TexMatrix(0, &layer->texmatrix);
10441 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10442 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10446 R_Mesh_TexBind(0, 0);
10447 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10449 R_Mesh_TexBind(1, 0);
10450 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10451 // generate a color array for the fog pass
10452 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10453 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10459 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10460 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)
10462 f = 1 - RSurf_FogVertex(v);
10463 c[0] = layercolor[0];
10464 c[1] = layercolor[1];
10465 c[2] = layercolor[2];
10466 c[3] = f * layercolor[3];
10469 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10472 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10476 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10478 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10479 GL_AlphaTest(false);
10483 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10485 // OpenGL 1.1 - crusty old voodoo path
10486 int texturesurfaceindex;
10489 const texturelayer_t *layer;
10490 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10492 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10494 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10496 if (layerindex == 0)
10497 GL_AlphaTest(true);
10500 GL_AlphaTest(false);
10501 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10504 GL_DepthMask(layer->depthmask && writedepth);
10505 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10506 R_Mesh_ColorPointer(NULL, 0, 0);
10507 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10508 switch (layer->type)
10510 case TEXTURELAYERTYPE_LITTEXTURE:
10511 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10513 // two-pass lit texture with 2x rgbscale
10514 // first the lightmap pass
10515 R_Mesh_TexBind(0, r_texture_white);
10516 R_Mesh_TexMatrix(0, NULL);
10517 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10518 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10519 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10520 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10521 else if (rsurface.uselightmaptexture)
10522 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10524 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10525 // then apply the texture to it
10526 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10527 R_Mesh_TexBind(0, layer->texture);
10528 R_Mesh_TexMatrix(0, &layer->texmatrix);
10529 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10530 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10531 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);
10535 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10536 R_Mesh_TexBind(0, layer->texture);
10537 R_Mesh_TexMatrix(0, &layer->texmatrix);
10538 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10539 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10540 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10541 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);
10543 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);
10546 case TEXTURELAYERTYPE_TEXTURE:
10547 // singletexture unlit texture with transparency support
10548 R_Mesh_TexBind(0, layer->texture);
10549 R_Mesh_TexMatrix(0, &layer->texmatrix);
10550 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10551 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10552 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);
10554 case TEXTURELAYERTYPE_FOG:
10555 // singletexture fogging
10556 if (layer->texture)
10558 R_Mesh_TexBind(0, layer->texture);
10559 R_Mesh_TexMatrix(0, &layer->texmatrix);
10560 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10561 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10565 R_Mesh_TexBind(0, 0);
10566 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10568 // generate a color array for the fog pass
10569 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10570 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10576 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10577 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)
10579 f = 1 - RSurf_FogVertex(v);
10580 c[0] = layer->color[0];
10581 c[1] = layer->color[1];
10582 c[2] = layer->color[2];
10583 c[3] = f * layer->color[3];
10586 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10589 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10593 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10595 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10596 GL_AlphaTest(false);
10600 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10604 GL_AlphaTest(false);
10605 R_Mesh_ColorPointer(NULL, 0, 0);
10606 R_Mesh_ResetTextureState();
10607 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10609 if(rsurface.texture && rsurface.texture->currentskinframe)
10611 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10612 c[3] *= rsurface.texture->currentalpha;
10622 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10624 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10625 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10626 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10629 // brighten it up (as texture value 127 means "unlit")
10630 c[0] *= 2 * r_refdef.view.colorscale;
10631 c[1] *= 2 * r_refdef.view.colorscale;
10632 c[2] *= 2 * r_refdef.view.colorscale;
10634 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10635 c[3] *= r_wateralpha.value;
10637 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10639 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10640 GL_DepthMask(false);
10642 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10644 GL_BlendFunc(GL_ONE, GL_ONE);
10645 GL_DepthMask(false);
10647 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10649 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10650 GL_DepthMask(false);
10652 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10654 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10655 GL_DepthMask(false);
10659 GL_BlendFunc(GL_ONE, GL_ZERO);
10660 GL_DepthMask(writedepth);
10663 rsurface.lightmapcolor4f = NULL;
10665 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10667 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10669 rsurface.lightmapcolor4f = NULL;
10670 rsurface.lightmapcolor4f_bufferobject = 0;
10671 rsurface.lightmapcolor4f_bufferoffset = 0;
10673 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10675 qboolean applycolor = true;
10678 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10680 r_refdef.lightmapintensity = 1;
10681 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10682 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10686 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10688 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10689 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10690 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10693 if(!rsurface.lightmapcolor4f)
10694 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10696 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10697 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10698 if(r_refdef.fogenabled)
10699 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10701 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10702 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10705 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10708 RSurf_SetupDepthAndCulling();
10709 if (r_showsurfaces.integer == 3 && !prepass)
10711 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10714 switch (vid.renderpath)
10716 case RENDERPATH_GL20:
10717 case RENDERPATH_CGGL:
10718 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10720 case RENDERPATH_GL13:
10721 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10723 case RENDERPATH_GL11:
10724 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10730 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10733 RSurf_SetupDepthAndCulling();
10734 if (r_showsurfaces.integer == 3 && !prepass)
10736 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10739 switch (vid.renderpath)
10741 case RENDERPATH_GL20:
10742 case RENDERPATH_CGGL:
10743 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10745 case RENDERPATH_GL13:
10746 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10748 case RENDERPATH_GL11:
10749 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10755 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10758 int texturenumsurfaces, endsurface;
10759 texture_t *texture;
10760 const msurface_t *surface;
10761 const msurface_t *texturesurfacelist[256];
10763 // if the model is static it doesn't matter what value we give for
10764 // wantnormals and wanttangents, so this logic uses only rules applicable
10765 // to a model, knowing that they are meaningless otherwise
10766 if (ent == r_refdef.scene.worldentity)
10767 RSurf_ActiveWorldEntity();
10768 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10769 RSurf_ActiveModelEntity(ent, false, false, false);
10772 switch (vid.renderpath)
10774 case RENDERPATH_GL20:
10775 case RENDERPATH_CGGL:
10776 RSurf_ActiveModelEntity(ent, true, true, false);
10778 case RENDERPATH_GL13:
10779 case RENDERPATH_GL11:
10780 RSurf_ActiveModelEntity(ent, true, false, false);
10785 if (r_transparentdepthmasking.integer)
10787 qboolean setup = false;
10788 for (i = 0;i < numsurfaces;i = j)
10791 surface = rsurface.modelsurfaces + surfacelist[i];
10792 texture = surface->texture;
10793 rsurface.texture = R_GetCurrentTexture(texture);
10794 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10795 // scan ahead until we find a different texture
10796 endsurface = min(i + 1024, numsurfaces);
10797 texturenumsurfaces = 0;
10798 texturesurfacelist[texturenumsurfaces++] = surface;
10799 for (;j < endsurface;j++)
10801 surface = rsurface.modelsurfaces + surfacelist[j];
10802 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10804 texturesurfacelist[texturenumsurfaces++] = surface;
10806 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10808 // render the range of surfaces as depth
10812 GL_ColorMask(0,0,0,0);
10814 GL_DepthTest(true);
10815 GL_BlendFunc(GL_ONE, GL_ZERO);
10816 GL_DepthMask(true);
10817 GL_AlphaTest(false);
10818 R_Mesh_ColorPointer(NULL, 0, 0);
10819 R_Mesh_ResetTextureState();
10820 R_SetupShader_DepthOrShadow();
10822 RSurf_SetupDepthAndCulling();
10823 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10824 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10827 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10830 for (i = 0;i < numsurfaces;i = j)
10833 surface = rsurface.modelsurfaces + surfacelist[i];
10834 texture = surface->texture;
10835 rsurface.texture = R_GetCurrentTexture(texture);
10836 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10837 // scan ahead until we find a different texture
10838 endsurface = min(i + 1024, numsurfaces);
10839 texturenumsurfaces = 0;
10840 texturesurfacelist[texturenumsurfaces++] = surface;
10841 for (;j < endsurface;j++)
10843 surface = rsurface.modelsurfaces + surfacelist[j];
10844 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10846 texturesurfacelist[texturenumsurfaces++] = surface;
10848 // render the range of surfaces
10849 if (ent == r_refdef.scene.worldentity)
10850 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10852 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10854 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10855 GL_AlphaTest(false);
10858 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10860 // transparent surfaces get pushed off into the transparent queue
10861 int surfacelistindex;
10862 const msurface_t *surface;
10863 vec3_t tempcenter, center;
10864 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10866 surface = texturesurfacelist[surfacelistindex];
10867 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10868 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10869 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10870 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10871 if (queueentity->transparent_offset) // transparent offset
10873 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10874 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10875 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10877 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10881 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10883 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10887 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10889 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10891 RSurf_SetupDepthAndCulling();
10892 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10893 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10897 if (!rsurface.texture->currentnumlayers)
10899 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10900 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10902 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10904 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10906 RSurf_SetupDepthAndCulling();
10907 GL_AlphaTest(false);
10908 R_Mesh_ColorPointer(NULL, 0, 0);
10909 R_Mesh_ResetTextureState();
10910 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10911 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10912 GL_DepthMask(true);
10913 GL_BlendFunc(GL_ONE, GL_ZERO);
10914 GL_Color(0, 0, 0, 1);
10915 GL_DepthTest(writedepth);
10916 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10918 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10920 RSurf_SetupDepthAndCulling();
10921 GL_AlphaTest(false);
10922 R_Mesh_ColorPointer(NULL, 0, 0);
10923 R_Mesh_ResetTextureState();
10924 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10925 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10926 GL_DepthMask(true);
10927 GL_BlendFunc(GL_ONE, GL_ZERO);
10928 GL_DepthTest(true);
10929 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10931 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10932 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10933 else if (!rsurface.texture->currentnumlayers)
10935 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10937 // in the deferred case, transparent surfaces were queued during prepass
10938 if (!r_shadow_usingdeferredprepass)
10939 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10943 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10944 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10949 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10952 texture_t *texture;
10953 // break the surface list down into batches by texture and use of lightmapping
10954 for (i = 0;i < numsurfaces;i = j)
10957 // texture is the base texture pointer, rsurface.texture is the
10958 // current frame/skin the texture is directing us to use (for example
10959 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10960 // use skin 1 instead)
10961 texture = surfacelist[i]->texture;
10962 rsurface.texture = R_GetCurrentTexture(texture);
10963 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10964 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10966 // if this texture is not the kind we want, skip ahead to the next one
10967 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10971 // simply scan ahead until we find a different texture or lightmap state
10972 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10974 // render the range of surfaces
10975 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10979 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10984 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10986 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10988 RSurf_SetupDepthAndCulling();
10989 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10990 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10994 if (!rsurface.texture->currentnumlayers)
10996 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10997 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10999 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11001 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11003 RSurf_SetupDepthAndCulling();
11004 GL_AlphaTest(false);
11005 R_Mesh_ColorPointer(NULL, 0, 0);
11006 R_Mesh_ResetTextureState();
11007 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11008 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11009 GL_DepthMask(true);
11010 GL_BlendFunc(GL_ONE, GL_ZERO);
11011 GL_Color(0, 0, 0, 1);
11012 GL_DepthTest(writedepth);
11013 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11015 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11017 RSurf_SetupDepthAndCulling();
11018 GL_AlphaTest(false);
11019 R_Mesh_ColorPointer(NULL, 0, 0);
11020 R_Mesh_ResetTextureState();
11021 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11022 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11023 GL_DepthMask(true);
11024 GL_BlendFunc(GL_ONE, GL_ZERO);
11025 GL_DepthTest(true);
11026 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11028 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11029 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11030 else if (!rsurface.texture->currentnumlayers)
11032 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11034 // in the deferred case, transparent surfaces were queued during prepass
11035 if (!r_shadow_usingdeferredprepass)
11036 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11040 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11041 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11046 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11049 texture_t *texture;
11050 // break the surface list down into batches by texture and use of lightmapping
11051 for (i = 0;i < numsurfaces;i = j)
11054 // texture is the base texture pointer, rsurface.texture is the
11055 // current frame/skin the texture is directing us to use (for example
11056 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11057 // use skin 1 instead)
11058 texture = surfacelist[i]->texture;
11059 rsurface.texture = R_GetCurrentTexture(texture);
11060 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11061 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11063 // if this texture is not the kind we want, skip ahead to the next one
11064 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11068 // simply scan ahead until we find a different texture or lightmap state
11069 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11071 // render the range of surfaces
11072 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11076 float locboxvertex3f[6*4*3] =
11078 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11079 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11080 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11081 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11082 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11083 1,0,0, 0,0,0, 0,1,0, 1,1,0
11086 unsigned short locboxelements[6*2*3] =
11091 12,13,14, 12,14,15,
11092 16,17,18, 16,18,19,
11096 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11099 cl_locnode_t *loc = (cl_locnode_t *)ent;
11101 float vertex3f[6*4*3];
11103 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11104 GL_DepthMask(false);
11105 GL_DepthRange(0, 1);
11106 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11107 GL_DepthTest(true);
11108 GL_CullFace(GL_NONE);
11109 R_EntityMatrix(&identitymatrix);
11111 R_Mesh_VertexPointer(vertex3f, 0, 0);
11112 R_Mesh_ColorPointer(NULL, 0, 0);
11113 R_Mesh_ResetTextureState();
11114 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11116 i = surfacelist[0];
11117 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11118 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11119 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11120 surfacelist[0] < 0 ? 0.5f : 0.125f);
11122 if (VectorCompare(loc->mins, loc->maxs))
11124 VectorSet(size, 2, 2, 2);
11125 VectorMA(loc->mins, -0.5f, size, mins);
11129 VectorCopy(loc->mins, mins);
11130 VectorSubtract(loc->maxs, loc->mins, size);
11133 for (i = 0;i < 6*4*3;)
11134 for (j = 0;j < 3;j++, i++)
11135 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11137 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11140 void R_DrawLocs(void)
11143 cl_locnode_t *loc, *nearestloc;
11145 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11146 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11148 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11149 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11153 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11155 if (decalsystem->decals)
11156 Mem_Free(decalsystem->decals);
11157 memset(decalsystem, 0, sizeof(*decalsystem));
11160 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)
11163 tridecal_t *decals;
11167 // expand or initialize the system
11168 if (decalsystem->maxdecals <= decalsystem->numdecals)
11170 decalsystem_t old = *decalsystem;
11171 qboolean useshortelements;
11172 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11173 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11174 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)));
11175 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11176 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11177 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11178 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11179 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11180 if (decalsystem->numdecals)
11181 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11183 Mem_Free(old.decals);
11184 for (i = 0;i < decalsystem->maxdecals*3;i++)
11185 decalsystem->element3i[i] = i;
11186 if (useshortelements)
11187 for (i = 0;i < decalsystem->maxdecals*3;i++)
11188 decalsystem->element3s[i] = i;
11191 // grab a decal and search for another free slot for the next one
11192 maxdecals = decalsystem->maxdecals;
11193 decals = decalsystem->decals;
11194 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11195 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11197 decalsystem->freedecal = i;
11198 if (decalsystem->numdecals <= i)
11199 decalsystem->numdecals = i + 1;
11201 // initialize the decal
11203 decal->triangleindex = triangleindex;
11204 decal->surfaceindex = surfaceindex;
11205 decal->decalsequence = decalsequence;
11206 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11207 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11208 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11209 decal->color4ub[0][3] = 255;
11210 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11211 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11212 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11213 decal->color4ub[1][3] = 255;
11214 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11215 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11216 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11217 decal->color4ub[2][3] = 255;
11218 decal->vertex3f[0][0] = v0[0];
11219 decal->vertex3f[0][1] = v0[1];
11220 decal->vertex3f[0][2] = v0[2];
11221 decal->vertex3f[1][0] = v1[0];
11222 decal->vertex3f[1][1] = v1[1];
11223 decal->vertex3f[1][2] = v1[2];
11224 decal->vertex3f[2][0] = v2[0];
11225 decal->vertex3f[2][1] = v2[1];
11226 decal->vertex3f[2][2] = v2[2];
11227 decal->texcoord2f[0][0] = t0[0];
11228 decal->texcoord2f[0][1] = t0[1];
11229 decal->texcoord2f[1][0] = t1[0];
11230 decal->texcoord2f[1][1] = t1[1];
11231 decal->texcoord2f[2][0] = t2[0];
11232 decal->texcoord2f[2][1] = t2[1];
11235 extern cvar_t cl_decals_bias;
11236 extern cvar_t cl_decals_models;
11237 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11238 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)
11240 matrix4x4_t projection;
11241 decalsystem_t *decalsystem;
11244 const float *vertex3f;
11245 const msurface_t *surface;
11246 const msurface_t *surfaces;
11247 const int *surfacelist;
11248 const texture_t *texture;
11251 int numsurfacelist;
11252 int surfacelistindex;
11255 int decalsurfaceindex;
11260 float localorigin[3];
11261 float localnormal[3];
11262 float localmins[3];
11263 float localmaxs[3];
11270 float planes[6][4];
11272 float points[2][9][3];
11276 decalsystem = &ent->decalsystem;
11277 model = ent->model;
11278 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11280 R_DecalSystem_Reset(&ent->decalsystem);
11284 if (!model->brush.data_nodes && !cl_decals_models.integer)
11286 if (decalsystem->model)
11287 R_DecalSystem_Reset(decalsystem);
11291 if (decalsystem->model != model)
11292 R_DecalSystem_Reset(decalsystem);
11293 decalsystem->model = model;
11295 RSurf_ActiveModelEntity(ent, false, false, false);
11297 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11298 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11299 VectorNormalize(localnormal);
11300 localsize = worldsize*rsurface.inversematrixscale;
11301 ilocalsize = 1.0f / localsize;
11302 localmins[0] = localorigin[0] - localsize;
11303 localmins[1] = localorigin[1] - localsize;
11304 localmins[2] = localorigin[2] - localsize;
11305 localmaxs[0] = localorigin[0] + localsize;
11306 localmaxs[1] = localorigin[1] + localsize;
11307 localmaxs[2] = localorigin[2] + localsize;
11309 //VectorCopy(localnormal, planes[4]);
11310 //VectorVectors(planes[4], planes[2], planes[0]);
11311 AnglesFromVectors(angles, localnormal, NULL, false);
11312 AngleVectors(angles, planes[0], planes[2], planes[4]);
11313 VectorNegate(planes[0], planes[1]);
11314 VectorNegate(planes[2], planes[3]);
11315 VectorNegate(planes[4], planes[5]);
11316 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11317 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11318 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11319 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11320 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11321 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11326 matrix4x4_t forwardprojection;
11327 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11328 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11333 float projectionvector[4][3];
11334 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11335 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11336 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11337 projectionvector[0][0] = planes[0][0] * ilocalsize;
11338 projectionvector[0][1] = planes[1][0] * ilocalsize;
11339 projectionvector[0][2] = planes[2][0] * ilocalsize;
11340 projectionvector[1][0] = planes[0][1] * ilocalsize;
11341 projectionvector[1][1] = planes[1][1] * ilocalsize;
11342 projectionvector[1][2] = planes[2][1] * ilocalsize;
11343 projectionvector[2][0] = planes[0][2] * ilocalsize;
11344 projectionvector[2][1] = planes[1][2] * ilocalsize;
11345 projectionvector[2][2] = planes[2][2] * ilocalsize;
11346 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11347 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11348 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11349 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11353 dynamic = model->surfmesh.isanimated;
11354 vertex3f = rsurface.modelvertex3f;
11355 numsurfacelist = model->nummodelsurfaces;
11356 surfacelist = model->sortedmodelsurfaces;
11357 surfaces = model->data_surfaces;
11358 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11360 surfaceindex = surfacelist[surfacelistindex];
11361 surface = surfaces + surfaceindex;
11362 // skip transparent surfaces
11363 texture = surface->texture;
11364 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11366 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11368 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11370 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11371 numvertices = surface->num_vertices;
11372 numtriangles = surface->num_triangles;
11373 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11375 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11377 index = 3*e[cornerindex];
11378 VectorCopy(vertex3f + index, v[cornerindex]);
11381 //TriangleNormal(v[0], v[1], v[2], normal);
11382 //if (DotProduct(normal, localnormal) < 0.0f)
11384 // clip by each of the box planes formed from the projection matrix
11385 // if anything survives, we emit the decal
11386 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]);
11389 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]);
11392 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]);
11395 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]);
11398 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]);
11401 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]);
11404 // some part of the triangle survived, so we have to accept it...
11407 // dynamic always uses the original triangle
11409 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11411 index = 3*e[cornerindex];
11412 VectorCopy(vertex3f + index, v[cornerindex]);
11415 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11417 // convert vertex positions to texcoords
11418 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11419 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11420 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11421 // calculate distance fade from the projection origin
11422 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11423 f = bound(0.0f, f, 1.0f);
11424 c[cornerindex][0] = r * f;
11425 c[cornerindex][1] = g * f;
11426 c[cornerindex][2] = b * f;
11427 c[cornerindex][3] = 1.0f;
11428 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11431 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);
11433 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11434 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);
11439 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11440 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)
11442 int renderentityindex;
11443 float worldmins[3];
11444 float worldmaxs[3];
11445 entity_render_t *ent;
11447 if (!cl_decals_newsystem.integer)
11450 worldmins[0] = worldorigin[0] - worldsize;
11451 worldmins[1] = worldorigin[1] - worldsize;
11452 worldmins[2] = worldorigin[2] - worldsize;
11453 worldmaxs[0] = worldorigin[0] + worldsize;
11454 worldmaxs[1] = worldorigin[1] + worldsize;
11455 worldmaxs[2] = worldorigin[2] + worldsize;
11457 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11459 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11461 ent = r_refdef.scene.entities[renderentityindex];
11462 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11465 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11469 typedef struct r_decalsystem_splatqueue_s
11471 vec3_t worldorigin;
11472 vec3_t worldnormal;
11478 r_decalsystem_splatqueue_t;
11480 int r_decalsystem_numqueued = 0;
11481 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11483 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)
11485 r_decalsystem_splatqueue_t *queue;
11487 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11490 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11491 VectorCopy(worldorigin, queue->worldorigin);
11492 VectorCopy(worldnormal, queue->worldnormal);
11493 Vector4Set(queue->color, r, g, b, a);
11494 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11495 queue->worldsize = worldsize;
11496 queue->decalsequence = cl.decalsequence++;
11499 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11502 r_decalsystem_splatqueue_t *queue;
11504 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11505 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);
11506 r_decalsystem_numqueued = 0;
11509 extern cvar_t cl_decals_max;
11510 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11513 decalsystem_t *decalsystem = &ent->decalsystem;
11520 if (!decalsystem->numdecals)
11523 if (r_showsurfaces.integer)
11526 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11528 R_DecalSystem_Reset(decalsystem);
11532 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11533 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11535 if (decalsystem->lastupdatetime)
11536 frametime = (cl.time - decalsystem->lastupdatetime);
11539 decalsystem->lastupdatetime = cl.time;
11540 decal = decalsystem->decals;
11541 numdecals = decalsystem->numdecals;
11543 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11545 if (decal->color4ub[0][3])
11547 decal->lived += frametime;
11548 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11550 memset(decal, 0, sizeof(*decal));
11551 if (decalsystem->freedecal > i)
11552 decalsystem->freedecal = i;
11556 decal = decalsystem->decals;
11557 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11560 // collapse the array by shuffling the tail decals into the gaps
11563 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11564 decalsystem->freedecal++;
11565 if (decalsystem->freedecal == numdecals)
11567 decal[decalsystem->freedecal] = decal[--numdecals];
11570 decalsystem->numdecals = numdecals;
11572 if (numdecals <= 0)
11574 // if there are no decals left, reset decalsystem
11575 R_DecalSystem_Reset(decalsystem);
11579 extern skinframe_t *decalskinframe;
11580 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11583 decalsystem_t *decalsystem = &ent->decalsystem;
11593 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11596 numdecals = decalsystem->numdecals;
11600 if (r_showsurfaces.integer)
11603 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11605 R_DecalSystem_Reset(decalsystem);
11609 // if the model is static it doesn't matter what value we give for
11610 // wantnormals and wanttangents, so this logic uses only rules applicable
11611 // to a model, knowing that they are meaningless otherwise
11612 if (ent == r_refdef.scene.worldentity)
11613 RSurf_ActiveWorldEntity();
11615 RSurf_ActiveModelEntity(ent, false, false, false);
11617 decalsystem->lastupdatetime = cl.time;
11618 decal = decalsystem->decals;
11620 fadedelay = cl_decals_time.value;
11621 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11623 // update vertex positions for animated models
11624 v3f = decalsystem->vertex3f;
11625 c4f = decalsystem->color4f;
11626 t2f = decalsystem->texcoord2f;
11627 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11629 if (!decal->color4ub[0][3])
11632 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11635 // update color values for fading decals
11636 if (decal->lived >= cl_decals_time.value)
11638 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11639 alpha *= (1.0f/255.0f);
11642 alpha = 1.0f/255.0f;
11644 c4f[ 0] = decal->color4ub[0][0] * alpha;
11645 c4f[ 1] = decal->color4ub[0][1] * alpha;
11646 c4f[ 2] = decal->color4ub[0][2] * alpha;
11648 c4f[ 4] = decal->color4ub[1][0] * alpha;
11649 c4f[ 5] = decal->color4ub[1][1] * alpha;
11650 c4f[ 6] = decal->color4ub[1][2] * alpha;
11652 c4f[ 8] = decal->color4ub[2][0] * alpha;
11653 c4f[ 9] = decal->color4ub[2][1] * alpha;
11654 c4f[10] = decal->color4ub[2][2] * alpha;
11657 t2f[0] = decal->texcoord2f[0][0];
11658 t2f[1] = decal->texcoord2f[0][1];
11659 t2f[2] = decal->texcoord2f[1][0];
11660 t2f[3] = decal->texcoord2f[1][1];
11661 t2f[4] = decal->texcoord2f[2][0];
11662 t2f[5] = decal->texcoord2f[2][1];
11664 // update vertex positions for animated models
11665 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11667 e = rsurface.modelelement3i + 3*decal->triangleindex;
11668 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11669 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11670 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11674 VectorCopy(decal->vertex3f[0], v3f);
11675 VectorCopy(decal->vertex3f[1], v3f + 3);
11676 VectorCopy(decal->vertex3f[2], v3f + 6);
11687 r_refdef.stats.drawndecals += numtris;
11689 if (r_refdef.fogenabled)
11691 switch(vid.renderpath)
11693 case RENDERPATH_GL20:
11694 case RENDERPATH_CGGL:
11695 case RENDERPATH_GL13:
11696 case RENDERPATH_GL11:
11697 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11699 alpha = RSurf_FogVertex(v3f);
11708 // now render the decals all at once
11709 // (this assumes they all use one particle font texture!)
11710 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);
11711 R_Mesh_ResetTextureState();
11712 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11713 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11714 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11715 GL_DepthMask(false);
11716 GL_DepthRange(0, 1);
11717 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11718 GL_DepthTest(true);
11719 GL_CullFace(GL_NONE);
11720 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11721 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11722 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11726 static void R_DrawModelDecals(void)
11730 // fade faster when there are too many decals
11731 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11732 for (i = 0;i < r_refdef.scene.numentities;i++)
11733 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11735 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11736 for (i = 0;i < r_refdef.scene.numentities;i++)
11737 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11738 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11740 R_DecalSystem_ApplySplatEntitiesQueue();
11742 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11743 for (i = 0;i < r_refdef.scene.numentities;i++)
11744 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11746 r_refdef.stats.totaldecals += numdecals;
11748 if (r_showsurfaces.integer)
11751 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11753 for (i = 0;i < r_refdef.scene.numentities;i++)
11755 if (!r_refdef.viewcache.entityvisible[i])
11757 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11758 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11762 void R_DrawDebugModel(void)
11764 entity_render_t *ent = rsurface.entity;
11765 int i, j, k, l, flagsmask;
11766 const int *elements;
11768 const msurface_t *surface;
11769 dp_model_t *model = ent->model;
11772 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11774 R_Mesh_ColorPointer(NULL, 0, 0);
11775 R_Mesh_ResetTextureState();
11776 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11777 GL_DepthRange(0, 1);
11778 GL_DepthTest(!r_showdisabledepthtest.integer);
11779 GL_DepthMask(false);
11780 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11782 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11784 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11785 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11787 if (brush->colbrushf && brush->colbrushf->numtriangles)
11789 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11790 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);
11791 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11794 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11796 if (surface->num_collisiontriangles)
11798 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11799 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);
11800 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11805 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11807 if (r_showtris.integer || r_shownormals.integer)
11809 if (r_showdisabledepthtest.integer)
11811 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11812 GL_DepthMask(false);
11816 GL_BlendFunc(GL_ONE, GL_ZERO);
11817 GL_DepthMask(true);
11819 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11821 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11823 rsurface.texture = R_GetCurrentTexture(surface->texture);
11824 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11826 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11827 if (r_showtris.value > 0)
11829 if (!rsurface.texture->currentlayers->depthmask)
11830 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11831 else if (ent == r_refdef.scene.worldentity)
11832 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11834 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11835 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11836 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11837 R_Mesh_ColorPointer(NULL, 0, 0);
11838 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11839 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11840 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11841 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);
11842 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11845 if (r_shownormals.value < 0)
11847 qglBegin(GL_LINES);
11848 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11850 VectorCopy(rsurface.vertex3f + l * 3, v);
11851 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11852 qglVertex3f(v[0], v[1], v[2]);
11853 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11854 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11855 qglVertex3f(v[0], v[1], v[2]);
11860 if (r_shownormals.value > 0)
11862 qglBegin(GL_LINES);
11863 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11865 VectorCopy(rsurface.vertex3f + l * 3, v);
11866 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11867 qglVertex3f(v[0], v[1], v[2]);
11868 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11869 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11870 qglVertex3f(v[0], v[1], v[2]);
11874 qglBegin(GL_LINES);
11875 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11877 VectorCopy(rsurface.vertex3f + l * 3, v);
11878 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11879 qglVertex3f(v[0], v[1], v[2]);
11880 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11881 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11882 qglVertex3f(v[0], v[1], v[2]);
11886 qglBegin(GL_LINES);
11887 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11889 VectorCopy(rsurface.vertex3f + l * 3, v);
11890 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11891 qglVertex3f(v[0], v[1], v[2]);
11892 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11893 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11894 qglVertex3f(v[0], v[1], v[2]);
11901 rsurface.texture = NULL;
11905 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11906 int r_maxsurfacelist = 0;
11907 const msurface_t **r_surfacelist = NULL;
11908 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11910 int i, j, endj, f, flagsmask;
11912 dp_model_t *model = r_refdef.scene.worldmodel;
11913 msurface_t *surfaces;
11914 unsigned char *update;
11915 int numsurfacelist = 0;
11919 if (r_maxsurfacelist < model->num_surfaces)
11921 r_maxsurfacelist = model->num_surfaces;
11923 Mem_Free((msurface_t**)r_surfacelist);
11924 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11927 RSurf_ActiveWorldEntity();
11929 surfaces = model->data_surfaces;
11930 update = model->brushq1.lightmapupdateflags;
11932 // update light styles on this submodel
11933 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11935 model_brush_lightstyleinfo_t *style;
11936 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11938 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11940 int *list = style->surfacelist;
11941 style->value = r_refdef.scene.lightstylevalue[style->style];
11942 for (j = 0;j < style->numsurfaces;j++)
11943 update[list[j]] = true;
11948 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11952 R_DrawDebugModel();
11953 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11959 rsurface.uselightmaptexture = false;
11960 rsurface.texture = NULL;
11961 rsurface.rtlight = NULL;
11962 numsurfacelist = 0;
11963 // add visible surfaces to draw list
11964 for (i = 0;i < model->nummodelsurfaces;i++)
11966 j = model->sortedmodelsurfaces[i];
11967 if (r_refdef.viewcache.world_surfacevisible[j])
11968 r_surfacelist[numsurfacelist++] = surfaces + j;
11970 // update lightmaps if needed
11971 if (model->brushq1.firstrender)
11973 model->brushq1.firstrender = false;
11974 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11976 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11980 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11981 if (r_refdef.viewcache.world_surfacevisible[j])
11983 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11985 // don't do anything if there were no surfaces
11986 if (!numsurfacelist)
11988 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11991 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11992 GL_AlphaTest(false);
11994 // add to stats if desired
11995 if (r_speeds.integer && !skysurfaces && !depthonly)
11997 r_refdef.stats.world_surfaces += numsurfacelist;
11998 for (j = 0;j < numsurfacelist;j++)
11999 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12002 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12005 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12007 int i, j, endj, f, flagsmask;
12009 dp_model_t *model = ent->model;
12010 msurface_t *surfaces;
12011 unsigned char *update;
12012 int numsurfacelist = 0;
12016 if (r_maxsurfacelist < model->num_surfaces)
12018 r_maxsurfacelist = model->num_surfaces;
12020 Mem_Free((msurface_t **)r_surfacelist);
12021 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12024 // if the model is static it doesn't matter what value we give for
12025 // wantnormals and wanttangents, so this logic uses only rules applicable
12026 // to a model, knowing that they are meaningless otherwise
12027 if (ent == r_refdef.scene.worldentity)
12028 RSurf_ActiveWorldEntity();
12029 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12030 RSurf_ActiveModelEntity(ent, false, false, false);
12032 RSurf_ActiveModelEntity(ent, true, true, true);
12033 else if (depthonly)
12034 RSurf_ActiveModelEntity(ent, false, false, false);
12037 switch (vid.renderpath)
12039 case RENDERPATH_GL20:
12040 case RENDERPATH_CGGL:
12041 RSurf_ActiveModelEntity(ent, true, true, false);
12043 case RENDERPATH_GL13:
12044 case RENDERPATH_GL11:
12045 RSurf_ActiveModelEntity(ent, true, false, false);
12050 surfaces = model->data_surfaces;
12051 update = model->brushq1.lightmapupdateflags;
12053 // update light styles
12054 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12056 model_brush_lightstyleinfo_t *style;
12057 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12059 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12061 int *list = style->surfacelist;
12062 style->value = r_refdef.scene.lightstylevalue[style->style];
12063 for (j = 0;j < style->numsurfaces;j++)
12064 update[list[j]] = true;
12069 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12073 R_DrawDebugModel();
12074 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12080 rsurface.uselightmaptexture = false;
12081 rsurface.texture = NULL;
12082 rsurface.rtlight = NULL;
12083 numsurfacelist = 0;
12084 // add visible surfaces to draw list
12085 for (i = 0;i < model->nummodelsurfaces;i++)
12086 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12087 // don't do anything if there were no surfaces
12088 if (!numsurfacelist)
12090 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12093 // update lightmaps if needed
12097 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12102 R_BuildLightMap(ent, surfaces + j);
12107 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12109 R_BuildLightMap(ent, surfaces + j);
12110 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12111 GL_AlphaTest(false);
12113 // add to stats if desired
12114 if (r_speeds.integer && !skysurfaces && !depthonly)
12116 r_refdef.stats.entities_surfaces += numsurfacelist;
12117 for (j = 0;j < numsurfacelist;j++)
12118 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12121 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12124 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12126 static texture_t texture;
12127 static msurface_t surface;
12128 const msurface_t *surfacelist = &surface;
12130 // fake enough texture and surface state to render this geometry
12132 texture.update_lastrenderframe = -1; // regenerate this texture
12133 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12134 texture.currentskinframe = skinframe;
12135 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12136 texture.specularscalemod = 1;
12137 texture.specularpowermod = 1;
12139 surface.texture = &texture;
12140 surface.num_triangles = numtriangles;
12141 surface.num_firsttriangle = firsttriangle;
12142 surface.num_vertices = numvertices;
12143 surface.num_firstvertex = firstvertex;
12146 rsurface.texture = R_GetCurrentTexture(surface.texture);
12147 rsurface.uselightmaptexture = false;
12148 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12151 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)
12153 static msurface_t surface;
12154 const msurface_t *surfacelist = &surface;
12156 // fake enough texture and surface state to render this geometry
12158 surface.texture = texture;
12159 surface.num_triangles = numtriangles;
12160 surface.num_firsttriangle = firsttriangle;
12161 surface.num_vertices = numvertices;
12162 surface.num_firstvertex = firstvertex;
12165 rsurface.texture = R_GetCurrentTexture(surface.texture);
12166 rsurface.uselightmaptexture = false;
12167 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);