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)
9709 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9710 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);
9712 else if (r_batchmode.integer == 2)
9714 #define MAXBATCHTRIANGLES 4096
9715 int batchtriangles = 0;
9716 static int batchelements[MAXBATCHTRIANGLES*3];
9717 for (i = 0;i < texturenumsurfaces;i = j)
9719 surface = texturesurfacelist[i];
9721 if (surface->num_triangles > MAXBATCHTRIANGLES)
9723 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);
9726 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9727 batchtriangles = surface->num_triangles;
9728 firstvertex = surface->num_firstvertex;
9729 endvertex = surface->num_firstvertex + surface->num_vertices;
9730 for (;j < texturenumsurfaces;j++)
9732 surface2 = texturesurfacelist[j];
9733 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9735 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9736 batchtriangles += surface2->num_triangles;
9737 firstvertex = min(firstvertex, surface2->num_firstvertex);
9738 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9740 surface2 = texturesurfacelist[j-1];
9741 numvertices = endvertex - firstvertex;
9742 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9745 else if (r_batchmode.integer == 1)
9747 for (i = 0;i < texturenumsurfaces;i = j)
9749 surface = texturesurfacelist[i];
9750 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9751 if (texturesurfacelist[j] != surface2)
9753 surface2 = texturesurfacelist[j-1];
9754 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9755 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9756 GL_LockArrays(surface->num_firstvertex, numvertices);
9757 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9762 for (i = 0;i < texturenumsurfaces;i++)
9764 surface = texturesurfacelist[i];
9765 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9766 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);
9771 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9773 switch(vid.renderpath)
9775 case RENDERPATH_CGGL:
9777 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9778 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9781 case RENDERPATH_GL20:
9782 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9783 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9785 case RENDERPATH_GL13:
9786 case RENDERPATH_GL11:
9787 R_Mesh_TexBind(0, surface->lightmaptexture);
9792 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9794 // pick the closest matching water plane and bind textures
9795 int planeindex, vertexindex;
9799 r_waterstate_waterplane_t *p, *bestp;
9802 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9805 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9807 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9808 d += fabs(PlaneDiff(vert, &p->plane));
9810 if (bestd > d || !bestp)
9816 switch(vid.renderpath)
9818 case RENDERPATH_CGGL:
9820 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9821 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9824 case RENDERPATH_GL20:
9825 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9826 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9828 case RENDERPATH_GL13:
9829 case RENDERPATH_GL11:
9834 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9837 const msurface_t *surface;
9838 if (r_waterstate.renderingscene)
9840 for (i = 0;i < texturenumsurfaces;i++)
9842 surface = texturesurfacelist[i];
9843 RSurf_BindLightmapForSurface(surface);
9844 RSurf_BindReflectionForSurface(surface);
9845 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9846 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);
9850 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9854 const msurface_t *surface = texturesurfacelist[0];
9855 const msurface_t *surface2;
9860 if (texturenumsurfaces == 1)
9862 RSurf_BindLightmapForSurface(surface);
9863 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9864 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);
9866 else if (r_batchmode.integer == 2)
9868 #define MAXBATCHTRIANGLES 4096
9869 int batchtriangles = 0;
9870 static int batchelements[MAXBATCHTRIANGLES*3];
9871 for (i = 0;i < texturenumsurfaces;i = j)
9873 surface = texturesurfacelist[i];
9874 RSurf_BindLightmapForSurface(surface);
9876 if (surface->num_triangles > MAXBATCHTRIANGLES)
9878 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);
9881 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9882 batchtriangles = surface->num_triangles;
9883 firstvertex = surface->num_firstvertex;
9884 endvertex = surface->num_firstvertex + surface->num_vertices;
9885 for (;j < texturenumsurfaces;j++)
9887 surface2 = texturesurfacelist[j];
9888 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9890 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9891 batchtriangles += surface2->num_triangles;
9892 firstvertex = min(firstvertex, surface2->num_firstvertex);
9893 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9895 surface2 = texturesurfacelist[j-1];
9896 numvertices = endvertex - firstvertex;
9897 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9900 else if (r_batchmode.integer == 1)
9903 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9904 for (i = 0;i < texturenumsurfaces;i = j)
9906 surface = texturesurfacelist[i];
9907 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9908 if (texturesurfacelist[j] != surface2)
9910 Con_Printf(" %i", j - i);
9913 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9915 for (i = 0;i < texturenumsurfaces;i = j)
9917 surface = texturesurfacelist[i];
9918 RSurf_BindLightmapForSurface(surface);
9919 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9920 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9923 Con_Printf(" %i", j - i);
9925 surface2 = texturesurfacelist[j-1];
9926 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9927 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9928 GL_LockArrays(surface->num_firstvertex, numvertices);
9929 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9937 for (i = 0;i < texturenumsurfaces;i++)
9939 surface = texturesurfacelist[i];
9940 RSurf_BindLightmapForSurface(surface);
9941 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9942 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);
9947 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9950 int texturesurfaceindex;
9951 if (r_showsurfaces.integer == 2)
9953 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9955 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9956 for (j = 0;j < surface->num_triangles;j++)
9958 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9959 GL_Color(f, f, f, 1);
9960 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9966 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9968 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9969 int k = (int)(((size_t)surface) / sizeof(msurface_t));
9970 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);
9971 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9972 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);
9977 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9979 int texturesurfaceindex;
9983 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9985 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9986 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)
9994 rsurface.lightmapcolor4f = rsurface.array_color4f;
9995 rsurface.lightmapcolor4f_bufferobject = 0;
9996 rsurface.lightmapcolor4f_bufferoffset = 0;
9999 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10001 int texturesurfaceindex;
10007 if (rsurface.lightmapcolor4f)
10009 // generate color arrays for the surfaces in this list
10010 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10012 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10013 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)
10015 f = RSurf_FogVertex(v);
10025 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10027 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10028 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)
10030 f = RSurf_FogVertex(v);
10038 rsurface.lightmapcolor4f = rsurface.array_color4f;
10039 rsurface.lightmapcolor4f_bufferobject = 0;
10040 rsurface.lightmapcolor4f_bufferoffset = 0;
10043 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10045 int texturesurfaceindex;
10051 if (!rsurface.lightmapcolor4f)
10053 // generate color arrays for the surfaces in this list
10054 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10056 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10057 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)
10059 f = RSurf_FogVertex(v);
10060 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10061 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10062 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10066 rsurface.lightmapcolor4f = rsurface.array_color4f;
10067 rsurface.lightmapcolor4f_bufferobject = 0;
10068 rsurface.lightmapcolor4f_bufferoffset = 0;
10071 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10073 int texturesurfaceindex;
10077 if (!rsurface.lightmapcolor4f)
10079 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10081 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10082 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)
10090 rsurface.lightmapcolor4f = rsurface.array_color4f;
10091 rsurface.lightmapcolor4f_bufferobject = 0;
10092 rsurface.lightmapcolor4f_bufferoffset = 0;
10095 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10097 int texturesurfaceindex;
10101 if (!rsurface.lightmapcolor4f)
10103 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10105 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10106 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)
10108 c2[0] = c[0] + r_refdef.scene.ambient;
10109 c2[1] = c[1] + r_refdef.scene.ambient;
10110 c2[2] = c[2] + r_refdef.scene.ambient;
10114 rsurface.lightmapcolor4f = rsurface.array_color4f;
10115 rsurface.lightmapcolor4f_bufferobject = 0;
10116 rsurface.lightmapcolor4f_bufferoffset = 0;
10119 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10122 rsurface.lightmapcolor4f = NULL;
10123 rsurface.lightmapcolor4f_bufferobject = 0;
10124 rsurface.lightmapcolor4f_bufferoffset = 0;
10125 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10126 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10127 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10128 GL_Color(r, g, b, a);
10129 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10132 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10134 // TODO: optimize applyfog && applycolor case
10135 // just apply fog if necessary, and tint the fog color array if necessary
10136 rsurface.lightmapcolor4f = NULL;
10137 rsurface.lightmapcolor4f_bufferobject = 0;
10138 rsurface.lightmapcolor4f_bufferoffset = 0;
10139 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10140 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10141 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10142 GL_Color(r, g, b, a);
10143 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10146 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10148 int texturesurfaceindex;
10152 if (texturesurfacelist[0]->lightmapinfo)
10154 // generate color arrays for the surfaces in this list
10155 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10157 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10158 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10160 if (surface->lightmapinfo->samples)
10162 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10163 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10164 VectorScale(lm, scale, c);
10165 if (surface->lightmapinfo->styles[1] != 255)
10167 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10169 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10170 VectorMA(c, scale, lm, c);
10171 if (surface->lightmapinfo->styles[2] != 255)
10174 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10175 VectorMA(c, scale, lm, c);
10176 if (surface->lightmapinfo->styles[3] != 255)
10179 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10180 VectorMA(c, scale, lm, c);
10190 rsurface.lightmapcolor4f = rsurface.array_color4f;
10191 rsurface.lightmapcolor4f_bufferobject = 0;
10192 rsurface.lightmapcolor4f_bufferoffset = 0;
10196 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10197 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10198 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10200 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10201 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10202 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10203 GL_Color(r, g, b, a);
10204 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10207 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10209 int texturesurfaceindex;
10216 vec3_t ambientcolor;
10217 vec3_t diffusecolor;
10221 VectorCopy(rsurface.modellight_lightdir, lightdir);
10222 f = 0.5f * r_refdef.lightmapintensity;
10223 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10224 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10225 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10226 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10227 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10228 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10230 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10232 // generate color arrays for the surfaces in this list
10233 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10235 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10236 int numverts = surface->num_vertices;
10237 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10238 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10239 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10240 // q3-style directional shading
10241 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10243 if ((f = DotProduct(n, lightdir)) > 0)
10244 VectorMA(ambientcolor, f, diffusecolor, c);
10246 VectorCopy(ambientcolor, c);
10254 rsurface.lightmapcolor4f = rsurface.array_color4f;
10255 rsurface.lightmapcolor4f_bufferobject = 0;
10256 rsurface.lightmapcolor4f_bufferoffset = 0;
10257 *applycolor = false;
10261 *r = ambientcolor[0];
10262 *g = ambientcolor[1];
10263 *b = ambientcolor[2];
10264 rsurface.lightmapcolor4f = NULL;
10265 rsurface.lightmapcolor4f_bufferobject = 0;
10266 rsurface.lightmapcolor4f_bufferoffset = 0;
10270 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10272 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10273 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10274 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10275 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10276 GL_Color(r, g, b, a);
10277 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10280 void RSurf_SetupDepthAndCulling(void)
10282 // submodels are biased to avoid z-fighting with world surfaces that they
10283 // may be exactly overlapping (avoids z-fighting artifacts on certain
10284 // doors and things in Quake maps)
10285 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10286 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10287 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10288 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10291 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10293 // transparent sky would be ridiculous
10294 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10296 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10297 skyrenderlater = true;
10298 RSurf_SetupDepthAndCulling();
10299 GL_DepthMask(true);
10300 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10301 // skymasking on them, and Quake3 never did sky masking (unlike
10302 // software Quake and software Quake2), so disable the sky masking
10303 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10304 // and skymasking also looks very bad when noclipping outside the
10305 // level, so don't use it then either.
10306 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10308 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10309 R_Mesh_ColorPointer(NULL, 0, 0);
10310 R_Mesh_ResetTextureState();
10311 if (skyrendermasked)
10313 R_SetupShader_DepthOrShadow();
10314 // depth-only (masking)
10315 GL_ColorMask(0,0,0,0);
10316 // just to make sure that braindead drivers don't draw
10317 // anything despite that colormask...
10318 GL_BlendFunc(GL_ZERO, GL_ONE);
10322 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10324 GL_BlendFunc(GL_ONE, GL_ZERO);
10326 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10327 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10328 if (skyrendermasked)
10329 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10331 R_Mesh_ResetTextureState();
10332 GL_Color(1, 1, 1, 1);
10335 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10336 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10337 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10339 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10342 // render screenspace normalmap to texture
10343 GL_DepthMask(true);
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_Simple(texturenumsurfaces, texturesurfacelist);
10346 GL_LockArrays(0, 0);
10348 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10350 // render water or distortion background, then blend surface on top
10351 GL_DepthMask(true);
10352 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10353 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10354 GL_LockArrays(0, 0);
10355 GL_DepthMask(false);
10356 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10357 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10358 GL_LockArrays(0, 0);
10362 // render surface normally
10363 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10364 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10365 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10366 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10367 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10368 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10370 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10371 GL_LockArrays(0, 0);
10375 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10377 // OpenGL 1.3 path - anything not completely ancient
10378 int texturesurfaceindex;
10379 qboolean applycolor;
10382 const texturelayer_t *layer;
10383 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10385 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10388 int layertexrgbscale;
10389 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10391 if (layerindex == 0)
10392 GL_AlphaTest(true);
10395 GL_AlphaTest(false);
10396 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10399 GL_DepthMask(layer->depthmask && writedepth);
10400 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10401 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10403 layertexrgbscale = 4;
10404 VectorScale(layer->color, 0.25f, layercolor);
10406 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10408 layertexrgbscale = 2;
10409 VectorScale(layer->color, 0.5f, layercolor);
10413 layertexrgbscale = 1;
10414 VectorScale(layer->color, 1.0f, layercolor);
10416 layercolor[3] = layer->color[3];
10417 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10418 R_Mesh_ColorPointer(NULL, 0, 0);
10419 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10420 switch (layer->type)
10422 case TEXTURELAYERTYPE_LITTEXTURE:
10423 // single-pass lightmapped texture with 2x rgbscale
10424 R_Mesh_TexBind(0, r_texture_white);
10425 R_Mesh_TexMatrix(0, NULL);
10426 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10427 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10428 R_Mesh_TexBind(1, layer->texture);
10429 R_Mesh_TexMatrix(1, &layer->texmatrix);
10430 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10431 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10432 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10433 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10434 else if (rsurface.uselightmaptexture)
10435 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10437 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10439 case TEXTURELAYERTYPE_TEXTURE:
10440 // singletexture unlit texture with transparency support
10441 R_Mesh_TexBind(0, layer->texture);
10442 R_Mesh_TexMatrix(0, &layer->texmatrix);
10443 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10444 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10445 R_Mesh_TexBind(1, 0);
10446 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10447 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10449 case TEXTURELAYERTYPE_FOG:
10450 // singletexture fogging
10451 if (layer->texture)
10453 R_Mesh_TexBind(0, layer->texture);
10454 R_Mesh_TexMatrix(0, &layer->texmatrix);
10455 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10456 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10460 R_Mesh_TexBind(0, 0);
10461 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10463 R_Mesh_TexBind(1, 0);
10464 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10465 // generate a color array for the fog pass
10466 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10467 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10473 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10474 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)
10476 f = 1 - RSurf_FogVertex(v);
10477 c[0] = layercolor[0];
10478 c[1] = layercolor[1];
10479 c[2] = layercolor[2];
10480 c[3] = f * layercolor[3];
10483 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10486 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10488 GL_LockArrays(0, 0);
10491 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10493 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10494 GL_AlphaTest(false);
10498 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10500 // OpenGL 1.1 - crusty old voodoo path
10501 int texturesurfaceindex;
10504 const texturelayer_t *layer;
10505 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10507 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10509 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10511 if (layerindex == 0)
10512 GL_AlphaTest(true);
10515 GL_AlphaTest(false);
10516 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10519 GL_DepthMask(layer->depthmask && writedepth);
10520 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10521 R_Mesh_ColorPointer(NULL, 0, 0);
10522 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10523 switch (layer->type)
10525 case TEXTURELAYERTYPE_LITTEXTURE:
10526 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10528 // two-pass lit texture with 2x rgbscale
10529 // first the lightmap pass
10530 R_Mesh_TexBind(0, r_texture_white);
10531 R_Mesh_TexMatrix(0, NULL);
10532 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10533 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10534 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10535 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10536 else if (rsurface.uselightmaptexture)
10537 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10539 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10540 GL_LockArrays(0, 0);
10541 // then apply the texture to it
10542 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10543 R_Mesh_TexBind(0, layer->texture);
10544 R_Mesh_TexMatrix(0, &layer->texmatrix);
10545 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10546 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10547 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);
10551 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10552 R_Mesh_TexBind(0, layer->texture);
10553 R_Mesh_TexMatrix(0, &layer->texmatrix);
10554 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10555 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10556 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10557 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);
10559 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);
10562 case TEXTURELAYERTYPE_TEXTURE:
10563 // singletexture unlit texture with transparency support
10564 R_Mesh_TexBind(0, layer->texture);
10565 R_Mesh_TexMatrix(0, &layer->texmatrix);
10566 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10567 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10568 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);
10570 case TEXTURELAYERTYPE_FOG:
10571 // singletexture fogging
10572 if (layer->texture)
10574 R_Mesh_TexBind(0, layer->texture);
10575 R_Mesh_TexMatrix(0, &layer->texmatrix);
10576 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10577 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10581 R_Mesh_TexBind(0, 0);
10582 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10584 // generate a color array for the fog pass
10585 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10586 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10592 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10593 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)
10595 f = 1 - RSurf_FogVertex(v);
10596 c[0] = layer->color[0];
10597 c[1] = layer->color[1];
10598 c[2] = layer->color[2];
10599 c[3] = f * layer->color[3];
10602 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10605 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10607 GL_LockArrays(0, 0);
10610 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10612 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10613 GL_AlphaTest(false);
10617 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10621 GL_AlphaTest(false);
10622 R_Mesh_ColorPointer(NULL, 0, 0);
10623 R_Mesh_ResetTextureState();
10624 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10626 if(rsurface.texture && rsurface.texture->currentskinframe)
10628 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10629 c[3] *= rsurface.texture->currentalpha;
10639 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10641 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10642 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10643 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10646 // brighten it up (as texture value 127 means "unlit")
10647 c[0] *= 2 * r_refdef.view.colorscale;
10648 c[1] *= 2 * r_refdef.view.colorscale;
10649 c[2] *= 2 * r_refdef.view.colorscale;
10651 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10652 c[3] *= r_wateralpha.value;
10654 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10656 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10657 GL_DepthMask(false);
10659 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10661 GL_BlendFunc(GL_ONE, GL_ONE);
10662 GL_DepthMask(false);
10664 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10666 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10667 GL_DepthMask(false);
10669 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10671 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10672 GL_DepthMask(false);
10676 GL_BlendFunc(GL_ONE, GL_ZERO);
10677 GL_DepthMask(writedepth);
10680 rsurface.lightmapcolor4f = NULL;
10682 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10684 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10686 rsurface.lightmapcolor4f = NULL;
10687 rsurface.lightmapcolor4f_bufferobject = 0;
10688 rsurface.lightmapcolor4f_bufferoffset = 0;
10690 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10692 qboolean applycolor = true;
10695 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10697 r_refdef.lightmapintensity = 1;
10698 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10699 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10703 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10705 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10706 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10707 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10710 if(!rsurface.lightmapcolor4f)
10711 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10713 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10714 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10715 if(r_refdef.fogenabled)
10716 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10718 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10719 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10722 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10725 RSurf_SetupDepthAndCulling();
10726 if (r_showsurfaces.integer == 3 && !prepass)
10728 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10731 switch (vid.renderpath)
10733 case RENDERPATH_GL20:
10734 case RENDERPATH_CGGL:
10735 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10737 case RENDERPATH_GL13:
10738 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10740 case RENDERPATH_GL11:
10741 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10747 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10750 RSurf_SetupDepthAndCulling();
10751 if (r_showsurfaces.integer == 3 && !prepass)
10753 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10756 switch (vid.renderpath)
10758 case RENDERPATH_GL20:
10759 case RENDERPATH_CGGL:
10760 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10762 case RENDERPATH_GL13:
10763 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10765 case RENDERPATH_GL11:
10766 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10772 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10775 int texturenumsurfaces, endsurface;
10776 texture_t *texture;
10777 const msurface_t *surface;
10778 const msurface_t *texturesurfacelist[256];
10780 // if the model is static it doesn't matter what value we give for
10781 // wantnormals and wanttangents, so this logic uses only rules applicable
10782 // to a model, knowing that they are meaningless otherwise
10783 if (ent == r_refdef.scene.worldentity)
10784 RSurf_ActiveWorldEntity();
10785 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10786 RSurf_ActiveModelEntity(ent, false, false, false);
10789 switch (vid.renderpath)
10791 case RENDERPATH_GL20:
10792 case RENDERPATH_CGGL:
10793 RSurf_ActiveModelEntity(ent, true, true, false);
10795 case RENDERPATH_GL13:
10796 case RENDERPATH_GL11:
10797 RSurf_ActiveModelEntity(ent, true, false, false);
10802 if (r_transparentdepthmasking.integer)
10804 qboolean setup = false;
10805 for (i = 0;i < numsurfaces;i = j)
10808 surface = rsurface.modelsurfaces + surfacelist[i];
10809 texture = surface->texture;
10810 rsurface.texture = R_GetCurrentTexture(texture);
10811 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10812 // scan ahead until we find a different texture
10813 endsurface = min(i + 1024, numsurfaces);
10814 texturenumsurfaces = 0;
10815 texturesurfacelist[texturenumsurfaces++] = surface;
10816 for (;j < endsurface;j++)
10818 surface = rsurface.modelsurfaces + surfacelist[j];
10819 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10821 texturesurfacelist[texturenumsurfaces++] = surface;
10823 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10825 // render the range of surfaces as depth
10829 GL_ColorMask(0,0,0,0);
10831 GL_DepthTest(true);
10832 GL_BlendFunc(GL_ONE, GL_ZERO);
10833 GL_DepthMask(true);
10834 GL_AlphaTest(false);
10835 R_Mesh_ColorPointer(NULL, 0, 0);
10836 R_Mesh_ResetTextureState();
10837 R_SetupShader_DepthOrShadow();
10839 RSurf_SetupDepthAndCulling();
10840 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10841 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10844 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10847 for (i = 0;i < numsurfaces;i = j)
10850 surface = rsurface.modelsurfaces + surfacelist[i];
10851 texture = surface->texture;
10852 rsurface.texture = R_GetCurrentTexture(texture);
10853 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10854 // scan ahead until we find a different texture
10855 endsurface = min(i + 1024, numsurfaces);
10856 texturenumsurfaces = 0;
10857 texturesurfacelist[texturenumsurfaces++] = surface;
10858 for (;j < endsurface;j++)
10860 surface = rsurface.modelsurfaces + surfacelist[j];
10861 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10863 texturesurfacelist[texturenumsurfaces++] = surface;
10865 // render the range of surfaces
10866 if (ent == r_refdef.scene.worldentity)
10867 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10869 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10871 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10872 GL_AlphaTest(false);
10875 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10877 // transparent surfaces get pushed off into the transparent queue
10878 int surfacelistindex;
10879 const msurface_t *surface;
10880 vec3_t tempcenter, center;
10881 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10883 surface = texturesurfacelist[surfacelistindex];
10884 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10885 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10886 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10887 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10888 if (queueentity->transparent_offset) // transparent offset
10890 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10891 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10892 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10894 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10898 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10900 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10904 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10906 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10908 RSurf_SetupDepthAndCulling();
10909 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10910 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10914 if (!rsurface.texture->currentnumlayers)
10916 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10917 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10919 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10921 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10923 RSurf_SetupDepthAndCulling();
10924 GL_AlphaTest(false);
10925 R_Mesh_ColorPointer(NULL, 0, 0);
10926 R_Mesh_ResetTextureState();
10927 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10928 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10929 GL_DepthMask(true);
10930 GL_BlendFunc(GL_ONE, GL_ZERO);
10931 GL_Color(0, 0, 0, 1);
10932 GL_DepthTest(writedepth);
10933 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10935 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10937 RSurf_SetupDepthAndCulling();
10938 GL_AlphaTest(false);
10939 R_Mesh_ColorPointer(NULL, 0, 0);
10940 R_Mesh_ResetTextureState();
10941 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10942 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10943 GL_DepthMask(true);
10944 GL_BlendFunc(GL_ONE, GL_ZERO);
10945 GL_DepthTest(true);
10946 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10948 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10949 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10950 else if (!rsurface.texture->currentnumlayers)
10952 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10954 // in the deferred case, transparent surfaces were queued during prepass
10955 if (!r_shadow_usingdeferredprepass)
10956 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10960 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10961 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10966 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10969 texture_t *texture;
10970 // break the surface list down into batches by texture and use of lightmapping
10971 for (i = 0;i < numsurfaces;i = j)
10974 // texture is the base texture pointer, rsurface.texture is the
10975 // current frame/skin the texture is directing us to use (for example
10976 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10977 // use skin 1 instead)
10978 texture = surfacelist[i]->texture;
10979 rsurface.texture = R_GetCurrentTexture(texture);
10980 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10981 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10983 // if this texture is not the kind we want, skip ahead to the next one
10984 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10988 // simply scan ahead until we find a different texture or lightmap state
10989 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10991 // render the range of surfaces
10992 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10996 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11001 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11003 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11005 RSurf_SetupDepthAndCulling();
11006 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11007 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11011 if (!rsurface.texture->currentnumlayers)
11013 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11014 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11016 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11018 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11020 RSurf_SetupDepthAndCulling();
11021 GL_AlphaTest(false);
11022 R_Mesh_ColorPointer(NULL, 0, 0);
11023 R_Mesh_ResetTextureState();
11024 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11025 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11026 GL_DepthMask(true);
11027 GL_BlendFunc(GL_ONE, GL_ZERO);
11028 GL_Color(0, 0, 0, 1);
11029 GL_DepthTest(writedepth);
11030 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11032 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11034 RSurf_SetupDepthAndCulling();
11035 GL_AlphaTest(false);
11036 R_Mesh_ColorPointer(NULL, 0, 0);
11037 R_Mesh_ResetTextureState();
11038 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11039 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11040 GL_DepthMask(true);
11041 GL_BlendFunc(GL_ONE, GL_ZERO);
11042 GL_DepthTest(true);
11043 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11045 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11046 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11047 else if (!rsurface.texture->currentnumlayers)
11049 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11051 // in the deferred case, transparent surfaces were queued during prepass
11052 if (!r_shadow_usingdeferredprepass)
11053 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11057 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11058 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11063 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11066 texture_t *texture;
11067 // break the surface list down into batches by texture and use of lightmapping
11068 for (i = 0;i < numsurfaces;i = j)
11071 // texture is the base texture pointer, rsurface.texture is the
11072 // current frame/skin the texture is directing us to use (for example
11073 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11074 // use skin 1 instead)
11075 texture = surfacelist[i]->texture;
11076 rsurface.texture = R_GetCurrentTexture(texture);
11077 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11078 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11080 // if this texture is not the kind we want, skip ahead to the next one
11081 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11085 // simply scan ahead until we find a different texture or lightmap state
11086 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11088 // render the range of surfaces
11089 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11093 float locboxvertex3f[6*4*3] =
11095 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11096 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11097 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11098 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11099 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11100 1,0,0, 0,0,0, 0,1,0, 1,1,0
11103 unsigned short locboxelements[6*2*3] =
11108 12,13,14, 12,14,15,
11109 16,17,18, 16,18,19,
11113 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11116 cl_locnode_t *loc = (cl_locnode_t *)ent;
11118 float vertex3f[6*4*3];
11120 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11121 GL_DepthMask(false);
11122 GL_DepthRange(0, 1);
11123 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11124 GL_DepthTest(true);
11125 GL_CullFace(GL_NONE);
11126 R_EntityMatrix(&identitymatrix);
11128 R_Mesh_VertexPointer(vertex3f, 0, 0);
11129 R_Mesh_ColorPointer(NULL, 0, 0);
11130 R_Mesh_ResetTextureState();
11131 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11133 i = surfacelist[0];
11134 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11135 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11136 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11137 surfacelist[0] < 0 ? 0.5f : 0.125f);
11139 if (VectorCompare(loc->mins, loc->maxs))
11141 VectorSet(size, 2, 2, 2);
11142 VectorMA(loc->mins, -0.5f, size, mins);
11146 VectorCopy(loc->mins, mins);
11147 VectorSubtract(loc->maxs, loc->mins, size);
11150 for (i = 0;i < 6*4*3;)
11151 for (j = 0;j < 3;j++, i++)
11152 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11154 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11157 void R_DrawLocs(void)
11160 cl_locnode_t *loc, *nearestloc;
11162 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11163 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11165 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11166 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11170 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11172 if (decalsystem->decals)
11173 Mem_Free(decalsystem->decals);
11174 memset(decalsystem, 0, sizeof(*decalsystem));
11177 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)
11180 tridecal_t *decals;
11184 // expand or initialize the system
11185 if (decalsystem->maxdecals <= decalsystem->numdecals)
11187 decalsystem_t old = *decalsystem;
11188 qboolean useshortelements;
11189 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11190 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11191 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)));
11192 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11193 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11194 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11195 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11196 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11197 if (decalsystem->numdecals)
11198 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11200 Mem_Free(old.decals);
11201 for (i = 0;i < decalsystem->maxdecals*3;i++)
11202 decalsystem->element3i[i] = i;
11203 if (useshortelements)
11204 for (i = 0;i < decalsystem->maxdecals*3;i++)
11205 decalsystem->element3s[i] = i;
11208 // grab a decal and search for another free slot for the next one
11209 maxdecals = decalsystem->maxdecals;
11210 decals = decalsystem->decals;
11211 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11212 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11214 decalsystem->freedecal = i;
11215 if (decalsystem->numdecals <= i)
11216 decalsystem->numdecals = i + 1;
11218 // initialize the decal
11220 decal->triangleindex = triangleindex;
11221 decal->surfaceindex = surfaceindex;
11222 decal->decalsequence = decalsequence;
11223 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11224 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11225 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11226 decal->color4ub[0][3] = 255;
11227 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11228 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11229 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11230 decal->color4ub[1][3] = 255;
11231 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11232 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11233 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11234 decal->color4ub[2][3] = 255;
11235 decal->vertex3f[0][0] = v0[0];
11236 decal->vertex3f[0][1] = v0[1];
11237 decal->vertex3f[0][2] = v0[2];
11238 decal->vertex3f[1][0] = v1[0];
11239 decal->vertex3f[1][1] = v1[1];
11240 decal->vertex3f[1][2] = v1[2];
11241 decal->vertex3f[2][0] = v2[0];
11242 decal->vertex3f[2][1] = v2[1];
11243 decal->vertex3f[2][2] = v2[2];
11244 decal->texcoord2f[0][0] = t0[0];
11245 decal->texcoord2f[0][1] = t0[1];
11246 decal->texcoord2f[1][0] = t1[0];
11247 decal->texcoord2f[1][1] = t1[1];
11248 decal->texcoord2f[2][0] = t2[0];
11249 decal->texcoord2f[2][1] = t2[1];
11252 extern cvar_t cl_decals_bias;
11253 extern cvar_t cl_decals_models;
11254 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11255 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)
11257 matrix4x4_t projection;
11258 decalsystem_t *decalsystem;
11261 const float *vertex3f;
11262 const msurface_t *surface;
11263 const msurface_t *surfaces;
11264 const int *surfacelist;
11265 const texture_t *texture;
11268 int numsurfacelist;
11269 int surfacelistindex;
11272 int decalsurfaceindex;
11277 float localorigin[3];
11278 float localnormal[3];
11279 float localmins[3];
11280 float localmaxs[3];
11287 float planes[6][4];
11289 float points[2][9][3];
11293 decalsystem = &ent->decalsystem;
11294 model = ent->model;
11295 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11297 R_DecalSystem_Reset(&ent->decalsystem);
11301 if (!model->brush.data_nodes && !cl_decals_models.integer)
11303 if (decalsystem->model)
11304 R_DecalSystem_Reset(decalsystem);
11308 if (decalsystem->model != model)
11309 R_DecalSystem_Reset(decalsystem);
11310 decalsystem->model = model;
11312 RSurf_ActiveModelEntity(ent, false, false, false);
11314 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11315 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11316 VectorNormalize(localnormal);
11317 localsize = worldsize*rsurface.inversematrixscale;
11318 ilocalsize = 1.0f / localsize;
11319 localmins[0] = localorigin[0] - localsize;
11320 localmins[1] = localorigin[1] - localsize;
11321 localmins[2] = localorigin[2] - localsize;
11322 localmaxs[0] = localorigin[0] + localsize;
11323 localmaxs[1] = localorigin[1] + localsize;
11324 localmaxs[2] = localorigin[2] + localsize;
11326 //VectorCopy(localnormal, planes[4]);
11327 //VectorVectors(planes[4], planes[2], planes[0]);
11328 AnglesFromVectors(angles, localnormal, NULL, false);
11329 AngleVectors(angles, planes[0], planes[2], planes[4]);
11330 VectorNegate(planes[0], planes[1]);
11331 VectorNegate(planes[2], planes[3]);
11332 VectorNegate(planes[4], planes[5]);
11333 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11334 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11335 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11336 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11337 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11338 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11343 matrix4x4_t forwardprojection;
11344 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11345 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11350 float projectionvector[4][3];
11351 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11352 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11353 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11354 projectionvector[0][0] = planes[0][0] * ilocalsize;
11355 projectionvector[0][1] = planes[1][0] * ilocalsize;
11356 projectionvector[0][2] = planes[2][0] * ilocalsize;
11357 projectionvector[1][0] = planes[0][1] * ilocalsize;
11358 projectionvector[1][1] = planes[1][1] * ilocalsize;
11359 projectionvector[1][2] = planes[2][1] * ilocalsize;
11360 projectionvector[2][0] = planes[0][2] * ilocalsize;
11361 projectionvector[2][1] = planes[1][2] * ilocalsize;
11362 projectionvector[2][2] = planes[2][2] * ilocalsize;
11363 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11364 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11365 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11366 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11370 dynamic = model->surfmesh.isanimated;
11371 vertex3f = rsurface.modelvertex3f;
11372 numsurfacelist = model->nummodelsurfaces;
11373 surfacelist = model->sortedmodelsurfaces;
11374 surfaces = model->data_surfaces;
11375 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11377 surfaceindex = surfacelist[surfacelistindex];
11378 surface = surfaces + surfaceindex;
11379 // skip transparent surfaces
11380 texture = surface->texture;
11381 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11383 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11385 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11387 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11388 numvertices = surface->num_vertices;
11389 numtriangles = surface->num_triangles;
11390 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11392 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11394 index = 3*e[cornerindex];
11395 VectorCopy(vertex3f + index, v[cornerindex]);
11398 //TriangleNormal(v[0], v[1], v[2], normal);
11399 //if (DotProduct(normal, localnormal) < 0.0f)
11401 // clip by each of the box planes formed from the projection matrix
11402 // if anything survives, we emit the decal
11403 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]);
11406 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]);
11409 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]);
11412 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]);
11415 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]);
11418 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]);
11421 // some part of the triangle survived, so we have to accept it...
11424 // dynamic always uses the original triangle
11426 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11428 index = 3*e[cornerindex];
11429 VectorCopy(vertex3f + index, v[cornerindex]);
11432 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11434 // convert vertex positions to texcoords
11435 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11436 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11437 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11438 // calculate distance fade from the projection origin
11439 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11440 f = bound(0.0f, f, 1.0f);
11441 c[cornerindex][0] = r * f;
11442 c[cornerindex][1] = g * f;
11443 c[cornerindex][2] = b * f;
11444 c[cornerindex][3] = 1.0f;
11445 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11448 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);
11450 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11451 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);
11456 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11457 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)
11459 int renderentityindex;
11460 float worldmins[3];
11461 float worldmaxs[3];
11462 entity_render_t *ent;
11464 if (!cl_decals_newsystem.integer)
11467 worldmins[0] = worldorigin[0] - worldsize;
11468 worldmins[1] = worldorigin[1] - worldsize;
11469 worldmins[2] = worldorigin[2] - worldsize;
11470 worldmaxs[0] = worldorigin[0] + worldsize;
11471 worldmaxs[1] = worldorigin[1] + worldsize;
11472 worldmaxs[2] = worldorigin[2] + worldsize;
11474 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11476 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11478 ent = r_refdef.scene.entities[renderentityindex];
11479 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11482 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11486 typedef struct r_decalsystem_splatqueue_s
11488 vec3_t worldorigin;
11489 vec3_t worldnormal;
11495 r_decalsystem_splatqueue_t;
11497 int r_decalsystem_numqueued = 0;
11498 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11500 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)
11502 r_decalsystem_splatqueue_t *queue;
11504 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11507 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11508 VectorCopy(worldorigin, queue->worldorigin);
11509 VectorCopy(worldnormal, queue->worldnormal);
11510 Vector4Set(queue->color, r, g, b, a);
11511 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11512 queue->worldsize = worldsize;
11513 queue->decalsequence = cl.decalsequence++;
11516 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11519 r_decalsystem_splatqueue_t *queue;
11521 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11522 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);
11523 r_decalsystem_numqueued = 0;
11526 extern cvar_t cl_decals_max;
11527 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11530 decalsystem_t *decalsystem = &ent->decalsystem;
11537 if (!decalsystem->numdecals)
11540 if (r_showsurfaces.integer)
11543 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11545 R_DecalSystem_Reset(decalsystem);
11549 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11550 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11552 if (decalsystem->lastupdatetime)
11553 frametime = (cl.time - decalsystem->lastupdatetime);
11556 decalsystem->lastupdatetime = cl.time;
11557 decal = decalsystem->decals;
11558 numdecals = decalsystem->numdecals;
11560 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11562 if (decal->color4ub[0][3])
11564 decal->lived += frametime;
11565 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11567 memset(decal, 0, sizeof(*decal));
11568 if (decalsystem->freedecal > i)
11569 decalsystem->freedecal = i;
11573 decal = decalsystem->decals;
11574 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11577 // collapse the array by shuffling the tail decals into the gaps
11580 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11581 decalsystem->freedecal++;
11582 if (decalsystem->freedecal == numdecals)
11584 decal[decalsystem->freedecal] = decal[--numdecals];
11587 decalsystem->numdecals = numdecals;
11589 if (numdecals <= 0)
11591 // if there are no decals left, reset decalsystem
11592 R_DecalSystem_Reset(decalsystem);
11596 extern skinframe_t *decalskinframe;
11597 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11600 decalsystem_t *decalsystem = &ent->decalsystem;
11610 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11613 numdecals = decalsystem->numdecals;
11617 if (r_showsurfaces.integer)
11620 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11622 R_DecalSystem_Reset(decalsystem);
11626 // if the model is static it doesn't matter what value we give for
11627 // wantnormals and wanttangents, so this logic uses only rules applicable
11628 // to a model, knowing that they are meaningless otherwise
11629 if (ent == r_refdef.scene.worldentity)
11630 RSurf_ActiveWorldEntity();
11632 RSurf_ActiveModelEntity(ent, false, false, false);
11634 decalsystem->lastupdatetime = cl.time;
11635 decal = decalsystem->decals;
11637 fadedelay = cl_decals_time.value;
11638 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11640 // update vertex positions for animated models
11641 v3f = decalsystem->vertex3f;
11642 c4f = decalsystem->color4f;
11643 t2f = decalsystem->texcoord2f;
11644 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11646 if (!decal->color4ub[0][3])
11649 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11652 // update color values for fading decals
11653 if (decal->lived >= cl_decals_time.value)
11655 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11656 alpha *= (1.0f/255.0f);
11659 alpha = 1.0f/255.0f;
11661 c4f[ 0] = decal->color4ub[0][0] * alpha;
11662 c4f[ 1] = decal->color4ub[0][1] * alpha;
11663 c4f[ 2] = decal->color4ub[0][2] * alpha;
11665 c4f[ 4] = decal->color4ub[1][0] * alpha;
11666 c4f[ 5] = decal->color4ub[1][1] * alpha;
11667 c4f[ 6] = decal->color4ub[1][2] * alpha;
11669 c4f[ 8] = decal->color4ub[2][0] * alpha;
11670 c4f[ 9] = decal->color4ub[2][1] * alpha;
11671 c4f[10] = decal->color4ub[2][2] * alpha;
11674 t2f[0] = decal->texcoord2f[0][0];
11675 t2f[1] = decal->texcoord2f[0][1];
11676 t2f[2] = decal->texcoord2f[1][0];
11677 t2f[3] = decal->texcoord2f[1][1];
11678 t2f[4] = decal->texcoord2f[2][0];
11679 t2f[5] = decal->texcoord2f[2][1];
11681 // update vertex positions for animated models
11682 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11684 e = rsurface.modelelement3i + 3*decal->triangleindex;
11685 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11686 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11687 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11691 VectorCopy(decal->vertex3f[0], v3f);
11692 VectorCopy(decal->vertex3f[1], v3f + 3);
11693 VectorCopy(decal->vertex3f[2], v3f + 6);
11704 r_refdef.stats.drawndecals += numtris;
11706 if (r_refdef.fogenabled)
11708 switch(vid.renderpath)
11710 case RENDERPATH_GL20:
11711 case RENDERPATH_CGGL:
11712 case RENDERPATH_GL13:
11713 case RENDERPATH_GL11:
11714 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11716 alpha = RSurf_FogVertex(v3f);
11725 // now render the decals all at once
11726 // (this assumes they all use one particle font texture!)
11727 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);
11728 R_Mesh_ResetTextureState();
11729 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11730 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11731 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11732 GL_DepthMask(false);
11733 GL_DepthRange(0, 1);
11734 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11735 GL_DepthTest(true);
11736 GL_CullFace(GL_NONE);
11737 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11738 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11739 GL_LockArrays(0, numtris * 3);
11740 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11741 GL_LockArrays(0, 0);
11745 static void R_DrawModelDecals(void)
11749 // fade faster when there are too many decals
11750 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11751 for (i = 0;i < r_refdef.scene.numentities;i++)
11752 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11754 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11755 for (i = 0;i < r_refdef.scene.numentities;i++)
11756 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11757 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11759 R_DecalSystem_ApplySplatEntitiesQueue();
11761 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11762 for (i = 0;i < r_refdef.scene.numentities;i++)
11763 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11765 r_refdef.stats.totaldecals += numdecals;
11767 if (r_showsurfaces.integer)
11770 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11772 for (i = 0;i < r_refdef.scene.numentities;i++)
11774 if (!r_refdef.viewcache.entityvisible[i])
11776 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11777 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11781 void R_DrawDebugModel(void)
11783 entity_render_t *ent = rsurface.entity;
11784 int i, j, k, l, flagsmask;
11785 const int *elements;
11787 const msurface_t *surface;
11788 dp_model_t *model = ent->model;
11791 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11793 R_Mesh_ColorPointer(NULL, 0, 0);
11794 R_Mesh_ResetTextureState();
11795 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11796 GL_DepthRange(0, 1);
11797 GL_DepthTest(!r_showdisabledepthtest.integer);
11798 GL_DepthMask(false);
11799 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11801 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11803 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11804 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11806 if (brush->colbrushf && brush->colbrushf->numtriangles)
11808 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11809 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);
11810 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11813 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11815 if (surface->num_collisiontriangles)
11817 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11818 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);
11819 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11824 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11826 if (r_showtris.integer || r_shownormals.integer)
11828 if (r_showdisabledepthtest.integer)
11830 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11831 GL_DepthMask(false);
11835 GL_BlendFunc(GL_ONE, GL_ZERO);
11836 GL_DepthMask(true);
11838 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11840 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11842 rsurface.texture = R_GetCurrentTexture(surface->texture);
11843 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11845 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11846 if (r_showtris.value > 0)
11848 if (!rsurface.texture->currentlayers->depthmask)
11849 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11850 else if (ent == r_refdef.scene.worldentity)
11851 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11853 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11854 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11855 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11856 R_Mesh_ColorPointer(NULL, 0, 0);
11857 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11858 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11859 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11860 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);
11861 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11864 if (r_shownormals.value < 0)
11866 qglBegin(GL_LINES);
11867 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11869 VectorCopy(rsurface.vertex3f + l * 3, v);
11870 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11871 qglVertex3f(v[0], v[1], v[2]);
11872 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11873 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11874 qglVertex3f(v[0], v[1], v[2]);
11879 if (r_shownormals.value > 0)
11881 qglBegin(GL_LINES);
11882 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11884 VectorCopy(rsurface.vertex3f + l * 3, v);
11885 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11886 qglVertex3f(v[0], v[1], v[2]);
11887 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11888 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11889 qglVertex3f(v[0], v[1], v[2]);
11893 qglBegin(GL_LINES);
11894 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11896 VectorCopy(rsurface.vertex3f + l * 3, v);
11897 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11898 qglVertex3f(v[0], v[1], v[2]);
11899 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11900 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11901 qglVertex3f(v[0], v[1], v[2]);
11905 qglBegin(GL_LINES);
11906 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11908 VectorCopy(rsurface.vertex3f + l * 3, v);
11909 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11910 qglVertex3f(v[0], v[1], v[2]);
11911 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11912 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11913 qglVertex3f(v[0], v[1], v[2]);
11920 rsurface.texture = NULL;
11924 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11925 int r_maxsurfacelist = 0;
11926 const msurface_t **r_surfacelist = NULL;
11927 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11929 int i, j, endj, f, flagsmask;
11931 dp_model_t *model = r_refdef.scene.worldmodel;
11932 msurface_t *surfaces;
11933 unsigned char *update;
11934 int numsurfacelist = 0;
11938 if (r_maxsurfacelist < model->num_surfaces)
11940 r_maxsurfacelist = model->num_surfaces;
11942 Mem_Free((msurface_t**)r_surfacelist);
11943 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11946 RSurf_ActiveWorldEntity();
11948 surfaces = model->data_surfaces;
11949 update = model->brushq1.lightmapupdateflags;
11951 // update light styles on this submodel
11952 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11954 model_brush_lightstyleinfo_t *style;
11955 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11957 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11959 int *list = style->surfacelist;
11960 style->value = r_refdef.scene.lightstylevalue[style->style];
11961 for (j = 0;j < style->numsurfaces;j++)
11962 update[list[j]] = true;
11967 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11971 R_DrawDebugModel();
11972 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11978 rsurface.uselightmaptexture = false;
11979 rsurface.texture = NULL;
11980 rsurface.rtlight = NULL;
11981 numsurfacelist = 0;
11982 // add visible surfaces to draw list
11983 for (i = 0;i < model->nummodelsurfaces;i++)
11985 j = model->sortedmodelsurfaces[i];
11986 if (r_refdef.viewcache.world_surfacevisible[j])
11987 r_surfacelist[numsurfacelist++] = surfaces + j;
11989 // update lightmaps if needed
11990 if (model->brushq1.firstrender)
11992 model->brushq1.firstrender = false;
11993 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11995 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11999 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12000 if (r_refdef.viewcache.world_surfacevisible[j])
12002 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12004 // don't do anything if there were no surfaces
12005 if (!numsurfacelist)
12007 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12010 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12011 GL_AlphaTest(false);
12013 // add to stats if desired
12014 if (r_speeds.integer && !skysurfaces && !depthonly)
12016 r_refdef.stats.world_surfaces += numsurfacelist;
12017 for (j = 0;j < numsurfacelist;j++)
12018 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12021 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12024 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12026 int i, j, endj, f, flagsmask;
12028 dp_model_t *model = ent->model;
12029 msurface_t *surfaces;
12030 unsigned char *update;
12031 int numsurfacelist = 0;
12035 if (r_maxsurfacelist < model->num_surfaces)
12037 r_maxsurfacelist = model->num_surfaces;
12039 Mem_Free((msurface_t **)r_surfacelist);
12040 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12043 // if the model is static it doesn't matter what value we give for
12044 // wantnormals and wanttangents, so this logic uses only rules applicable
12045 // to a model, knowing that they are meaningless otherwise
12046 if (ent == r_refdef.scene.worldentity)
12047 RSurf_ActiveWorldEntity();
12048 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12049 RSurf_ActiveModelEntity(ent, false, false, false);
12051 RSurf_ActiveModelEntity(ent, true, true, true);
12052 else if (depthonly)
12053 RSurf_ActiveModelEntity(ent, false, false, false);
12056 switch (vid.renderpath)
12058 case RENDERPATH_GL20:
12059 case RENDERPATH_CGGL:
12060 RSurf_ActiveModelEntity(ent, true, true, false);
12062 case RENDERPATH_GL13:
12063 case RENDERPATH_GL11:
12064 RSurf_ActiveModelEntity(ent, true, false, false);
12069 surfaces = model->data_surfaces;
12070 update = model->brushq1.lightmapupdateflags;
12072 // update light styles
12073 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12075 model_brush_lightstyleinfo_t *style;
12076 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12078 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12080 int *list = style->surfacelist;
12081 style->value = r_refdef.scene.lightstylevalue[style->style];
12082 for (j = 0;j < style->numsurfaces;j++)
12083 update[list[j]] = true;
12088 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12092 R_DrawDebugModel();
12093 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12099 rsurface.uselightmaptexture = false;
12100 rsurface.texture = NULL;
12101 rsurface.rtlight = NULL;
12102 numsurfacelist = 0;
12103 // add visible surfaces to draw list
12104 for (i = 0;i < model->nummodelsurfaces;i++)
12105 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12106 // don't do anything if there were no surfaces
12107 if (!numsurfacelist)
12109 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12112 // update lightmaps if needed
12116 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12121 R_BuildLightMap(ent, surfaces + j);
12126 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12128 R_BuildLightMap(ent, surfaces + j);
12129 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12130 GL_AlphaTest(false);
12132 // add to stats if desired
12133 if (r_speeds.integer && !skysurfaces && !depthonly)
12135 r_refdef.stats.entities_surfaces += numsurfacelist;
12136 for (j = 0;j < numsurfacelist;j++)
12137 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12140 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12143 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12145 static texture_t texture;
12146 static msurface_t surface;
12147 const msurface_t *surfacelist = &surface;
12149 // fake enough texture and surface state to render this geometry
12151 texture.update_lastrenderframe = -1; // regenerate this texture
12152 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12153 texture.currentskinframe = skinframe;
12154 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12155 texture.specularscalemod = 1;
12156 texture.specularpowermod = 1;
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);
12170 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)
12172 static msurface_t surface;
12173 const msurface_t *surfacelist = &surface;
12175 // fake enough texture and surface state to render this geometry
12177 surface.texture = texture;
12178 surface.num_triangles = numtriangles;
12179 surface.num_firsttriangle = firsttriangle;
12180 surface.num_vertices = numvertices;
12181 surface.num_firstvertex = firstvertex;
12184 rsurface.texture = R_GetCurrentTexture(surface.texture);
12185 rsurface.uselightmaptexture = false;
12186 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);