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 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7780 if (!r_drawentities.integer)
7781 r_refdef.scene.numentities = 0;
7783 R_AnimCache_ClearCache();
7784 R_FrameData_NewFrame();
7786 if (r_refdef.view.isoverlay)
7788 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7789 GL_Clear( GL_DEPTH_BUFFER_BIT );
7790 R_TimeReport("depthclear");
7792 r_refdef.view.showdebug = false;
7794 r_waterstate.enabled = false;
7795 r_waterstate.numwaterplanes = 0;
7803 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7804 return; //Host_Error ("R_RenderView: NULL worldmodel");
7806 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7808 // break apart the view matrix into vectors for various purposes
7809 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7810 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7811 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7812 VectorNegate(r_refdef.view.left, r_refdef.view.right);
7813 // make an inverted copy of the view matrix for tracking sprites
7814 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7816 R_Shadow_UpdateWorldLightSelection();
7818 R_Bloom_StartFrame();
7819 R_Water_StartFrame();
7822 if (r_timereport_active)
7823 R_TimeReport("viewsetup");
7825 R_ResetViewRendering3D();
7827 if (r_refdef.view.clear || r_refdef.fogenabled)
7829 R_ClearScreen(r_refdef.fogenabled);
7830 if (r_timereport_active)
7831 R_TimeReport("viewclear");
7833 r_refdef.view.clear = true;
7835 // this produces a bloom texture to be used in R_BlendView() later
7836 if (r_hdr.integer && r_bloomstate.bloomwidth)
7837 R_HDR_RenderBloomTexture();
7839 r_refdef.view.showdebug = true;
7842 if (r_timereport_active)
7843 R_TimeReport("visibility");
7845 r_waterstate.numwaterplanes = 0;
7846 if (r_waterstate.enabled)
7847 R_RenderWaterPlanes();
7850 r_waterstate.numwaterplanes = 0;
7853 if (r_timereport_active)
7854 R_TimeReport("blendview");
7856 GL_Scissor(0, 0, vid.width, vid.height);
7857 GL_ScissorTest(false);
7861 void R_RenderWaterPlanes(void)
7863 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7865 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7866 if (r_timereport_active)
7867 R_TimeReport("waterworld");
7870 // don't let sound skip if going slow
7871 if (r_refdef.scene.extraupdate)
7874 R_DrawModelsAddWaterPlanes();
7875 if (r_timereport_active)
7876 R_TimeReport("watermodels");
7878 if (r_waterstate.numwaterplanes)
7880 R_Water_ProcessPlanes();
7881 if (r_timereport_active)
7882 R_TimeReport("waterscenes");
7886 extern void R_DrawLightningBeams (void);
7887 extern void VM_CL_AddPolygonsToMeshQueue (void);
7888 extern void R_DrawPortals (void);
7889 extern cvar_t cl_locs_show;
7890 static void R_DrawLocs(void);
7891 static void R_DrawEntityBBoxes(void);
7892 static void R_DrawModelDecals(void);
7893 extern cvar_t cl_decals_newsystem;
7894 extern qboolean r_shadow_usingdeferredprepass;
7895 void R_RenderScene(void)
7897 r_refdef.stats.renders++;
7898 r_textureframe++; // used only by R_GetCurrentTexture
7902 // don't let sound skip if going slow
7903 if (r_refdef.scene.extraupdate)
7906 R_MeshQueue_BeginScene();
7910 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);
7912 if (cl.csqc_vidvars.drawworld)
7914 // don't let sound skip if going slow
7915 if (r_refdef.scene.extraupdate)
7918 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7920 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7921 if (r_timereport_active)
7922 R_TimeReport("worldsky");
7925 if (R_DrawBrushModelsSky() && r_timereport_active)
7926 R_TimeReport("bmodelsky");
7928 if (skyrendermasked && skyrenderlater)
7930 // we have to force off the water clipping plane while rendering sky
7934 if (r_timereport_active)
7935 R_TimeReport("sky");
7939 R_AnimCache_CacheVisibleEntities();
7940 if (r_timereport_active)
7941 R_TimeReport("animation");
7943 R_Shadow_PrepareLights();
7944 if (r_timereport_active)
7945 R_TimeReport("preparelights");
7947 if (r_shadow_usingdeferredprepass)
7948 R_Shadow_DrawPrepass();
7950 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7952 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7953 if (r_timereport_active)
7954 R_TimeReport("worlddepth");
7956 if (r_depthfirst.integer >= 2)
7958 R_DrawModelsDepth();
7959 if (r_timereport_active)
7960 R_TimeReport("modeldepth");
7963 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7965 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7966 if (r_timereport_active)
7967 R_TimeReport("world");
7970 // don't let sound skip if going slow
7971 if (r_refdef.scene.extraupdate)
7975 if (r_timereport_active)
7976 R_TimeReport("models");
7978 // don't let sound skip if going slow
7979 if (r_refdef.scene.extraupdate)
7982 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7984 R_DrawModelShadows();
7985 R_ResetViewRendering3D();
7986 // don't let sound skip if going slow
7987 if (r_refdef.scene.extraupdate)
7991 if (!r_shadow_usingdeferredprepass)
7993 R_Shadow_DrawLights();
7994 if (r_timereport_active)
7995 R_TimeReport("rtlights");
7998 // don't let sound skip if going slow
7999 if (r_refdef.scene.extraupdate)
8002 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8004 R_DrawModelShadows();
8005 R_ResetViewRendering3D();
8006 // don't let sound skip if going slow
8007 if (r_refdef.scene.extraupdate)
8011 if (cl.csqc_vidvars.drawworld)
8013 if (cl_decals_newsystem.integer)
8015 R_DrawModelDecals();
8016 if (r_timereport_active)
8017 R_TimeReport("modeldecals");
8022 if (r_timereport_active)
8023 R_TimeReport("decals");
8027 if (r_timereport_active)
8028 R_TimeReport("particles");
8031 if (r_timereport_active)
8032 R_TimeReport("explosions");
8034 R_DrawLightningBeams();
8035 if (r_timereport_active)
8036 R_TimeReport("lightning");
8039 VM_CL_AddPolygonsToMeshQueue();
8041 if (r_refdef.view.showdebug)
8043 if (cl_locs_show.integer)
8046 if (r_timereport_active)
8047 R_TimeReport("showlocs");
8050 if (r_drawportals.integer)
8053 if (r_timereport_active)
8054 R_TimeReport("portals");
8057 if (r_showbboxes.value > 0)
8059 R_DrawEntityBBoxes();
8060 if (r_timereport_active)
8061 R_TimeReport("bboxes");
8065 R_MeshQueue_RenderTransparent();
8066 if (r_timereport_active)
8067 R_TimeReport("drawtrans");
8069 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))
8071 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8072 if (r_timereport_active)
8073 R_TimeReport("worlddebug");
8074 R_DrawModelsDebug();
8075 if (r_timereport_active)
8076 R_TimeReport("modeldebug");
8079 if (cl.csqc_vidvars.drawworld)
8081 R_Shadow_DrawCoronas();
8082 if (r_timereport_active)
8083 R_TimeReport("coronas");
8086 // don't let sound skip if going slow
8087 if (r_refdef.scene.extraupdate)
8090 R_ResetViewRendering2D();
8093 static const unsigned short bboxelements[36] =
8103 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8106 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8108 RSurf_ActiveWorldEntity();
8110 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8111 GL_DepthMask(false);
8112 GL_DepthRange(0, 1);
8113 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8114 R_Mesh_ResetTextureState();
8116 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8117 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8118 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8119 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8120 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8121 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8122 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8123 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8124 R_FillColors(color4f, 8, cr, cg, cb, ca);
8125 if (r_refdef.fogenabled)
8127 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8129 f1 = RSurf_FogVertex(v);
8131 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8132 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8133 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8136 R_Mesh_VertexPointer(vertex3f, 0, 0);
8137 R_Mesh_ColorPointer(color4f, 0, 0);
8138 R_Mesh_ResetTextureState();
8139 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8140 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8143 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8147 prvm_edict_t *edict;
8148 prvm_prog_t *prog_save = prog;
8150 // this function draws bounding boxes of server entities
8154 GL_CullFace(GL_NONE);
8155 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8159 for (i = 0;i < numsurfaces;i++)
8161 edict = PRVM_EDICT_NUM(surfacelist[i]);
8162 switch ((int)edict->fields.server->solid)
8164 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
8165 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
8166 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
8167 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8168 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
8169 default: Vector4Set(color, 0, 0, 0, 0.50);break;
8171 color[3] *= r_showbboxes.value;
8172 color[3] = bound(0, color[3], 1);
8173 GL_DepthTest(!r_showdisabledepthtest.integer);
8174 GL_CullFace(r_refdef.view.cullface_front);
8175 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8181 static void R_DrawEntityBBoxes(void)
8184 prvm_edict_t *edict;
8186 prvm_prog_t *prog_save = prog;
8188 // this function draws bounding boxes of server entities
8194 for (i = 0;i < prog->num_edicts;i++)
8196 edict = PRVM_EDICT_NUM(i);
8197 if (edict->priv.server->free)
8199 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8200 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8202 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8204 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8205 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8211 static const int nomodelelement3i[24] =
8223 static const unsigned short nomodelelement3s[24] =
8235 static const float nomodelvertex3f[6*3] =
8245 static const float nomodelcolor4f[6*4] =
8247 0.0f, 0.0f, 0.5f, 1.0f,
8248 0.0f, 0.0f, 0.5f, 1.0f,
8249 0.0f, 0.5f, 0.0f, 1.0f,
8250 0.0f, 0.5f, 0.0f, 1.0f,
8251 0.5f, 0.0f, 0.0f, 1.0f,
8252 0.5f, 0.0f, 0.0f, 1.0f
8255 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8261 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);
8263 // this is only called once per entity so numsurfaces is always 1, and
8264 // surfacelist is always {0}, so this code does not handle batches
8266 if (rsurface.ent_flags & RENDER_ADDITIVE)
8268 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8269 GL_DepthMask(false);
8271 else if (rsurface.colormod[3] < 1)
8273 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8274 GL_DepthMask(false);
8278 GL_BlendFunc(GL_ONE, GL_ZERO);
8281 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8282 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8283 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8284 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8285 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8286 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8287 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8288 R_Mesh_ColorPointer(color4f, 0, 0);
8289 for (i = 0, c = color4f;i < 6;i++, c += 4)
8291 c[0] *= rsurface.colormod[0];
8292 c[1] *= rsurface.colormod[1];
8293 c[2] *= rsurface.colormod[2];
8294 c[3] *= rsurface.colormod[3];
8296 if (r_refdef.fogenabled)
8298 for (i = 0, c = color4f;i < 6;i++, c += 4)
8300 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8302 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8303 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8304 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8307 R_Mesh_ResetTextureState();
8308 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8311 void R_DrawNoModel(entity_render_t *ent)
8314 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8315 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8316 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8318 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8321 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8323 vec3_t right1, right2, diff, normal;
8325 VectorSubtract (org2, org1, normal);
8327 // calculate 'right' vector for start
8328 VectorSubtract (r_refdef.view.origin, org1, diff);
8329 CrossProduct (normal, diff, right1);
8330 VectorNormalize (right1);
8332 // calculate 'right' vector for end
8333 VectorSubtract (r_refdef.view.origin, org2, diff);
8334 CrossProduct (normal, diff, right2);
8335 VectorNormalize (right2);
8337 vert[ 0] = org1[0] + width * right1[0];
8338 vert[ 1] = org1[1] + width * right1[1];
8339 vert[ 2] = org1[2] + width * right1[2];
8340 vert[ 3] = org1[0] - width * right1[0];
8341 vert[ 4] = org1[1] - width * right1[1];
8342 vert[ 5] = org1[2] - width * right1[2];
8343 vert[ 6] = org2[0] - width * right2[0];
8344 vert[ 7] = org2[1] - width * right2[1];
8345 vert[ 8] = org2[2] - width * right2[2];
8346 vert[ 9] = org2[0] + width * right2[0];
8347 vert[10] = org2[1] + width * right2[1];
8348 vert[11] = org2[2] + width * right2[2];
8351 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)
8353 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8354 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8355 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8356 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8357 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8358 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8359 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8360 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8361 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8362 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8363 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8364 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8367 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8372 VectorSet(v, x, y, z);
8373 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8374 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8376 if (i == mesh->numvertices)
8378 if (mesh->numvertices < mesh->maxvertices)
8380 VectorCopy(v, vertex3f);
8381 mesh->numvertices++;
8383 return mesh->numvertices;
8389 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8393 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8394 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8395 e = mesh->element3i + mesh->numtriangles * 3;
8396 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8398 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8399 if (mesh->numtriangles < mesh->maxtriangles)
8404 mesh->numtriangles++;
8406 element[1] = element[2];
8410 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8414 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8415 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8416 e = mesh->element3i + mesh->numtriangles * 3;
8417 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8419 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8420 if (mesh->numtriangles < mesh->maxtriangles)
8425 mesh->numtriangles++;
8427 element[1] = element[2];
8431 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8432 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8434 int planenum, planenum2;
8437 mplane_t *plane, *plane2;
8439 double temppoints[2][256*3];
8440 // figure out how large a bounding box we need to properly compute this brush
8442 for (w = 0;w < numplanes;w++)
8443 maxdist = max(maxdist, fabs(planes[w].dist));
8444 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8445 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8446 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8450 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8451 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8453 if (planenum2 == planenum)
8455 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);
8458 if (tempnumpoints < 3)
8460 // generate elements forming a triangle fan for this polygon
8461 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8465 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)
8467 texturelayer_t *layer;
8468 layer = t->currentlayers + t->currentnumlayers++;
8470 layer->depthmask = depthmask;
8471 layer->blendfunc1 = blendfunc1;
8472 layer->blendfunc2 = blendfunc2;
8473 layer->texture = texture;
8474 layer->texmatrix = *matrix;
8475 layer->color[0] = r;
8476 layer->color[1] = g;
8477 layer->color[2] = b;
8478 layer->color[3] = a;
8481 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8484 index = parms[2] + r_refdef.scene.time * parms[3];
8485 index -= floor(index);
8489 case Q3WAVEFUNC_NONE:
8490 case Q3WAVEFUNC_NOISE:
8491 case Q3WAVEFUNC_COUNT:
8494 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8495 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8496 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8497 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8498 case Q3WAVEFUNC_TRIANGLE:
8500 f = index - floor(index);
8511 return (float)(parms[0] + parms[1] * f);
8514 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8519 matrix4x4_t matrix, temp;
8520 switch(tcmod->tcmod)
8524 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8525 matrix = r_waterscrollmatrix;
8527 matrix = identitymatrix;
8529 case Q3TCMOD_ENTITYTRANSLATE:
8530 // this is used in Q3 to allow the gamecode to control texcoord
8531 // scrolling on the entity, which is not supported in darkplaces yet.
8532 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8534 case Q3TCMOD_ROTATE:
8535 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8536 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8537 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8540 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8542 case Q3TCMOD_SCROLL:
8543 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8545 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8546 w = (int) tcmod->parms[0];
8547 h = (int) tcmod->parms[1];
8548 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8550 idx = (int) floor(f * w * h);
8551 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8553 case Q3TCMOD_STRETCH:
8554 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8555 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8557 case Q3TCMOD_TRANSFORM:
8558 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8559 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8560 VectorSet(tcmat + 6, 0 , 0 , 1);
8561 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8562 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8564 case Q3TCMOD_TURBULENT:
8565 // this is handled in the RSurf_PrepareVertices function
8566 matrix = identitymatrix;
8570 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8573 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8575 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8576 char name[MAX_QPATH];
8577 skinframe_t *skinframe;
8578 unsigned char pixels[296*194];
8579 strlcpy(cache->name, skinname, sizeof(cache->name));
8580 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8581 if (developer_loading.integer)
8582 Con_Printf("loading %s\n", name);
8583 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8584 if (!skinframe || !skinframe->base)
8587 fs_offset_t filesize;
8589 f = FS_LoadFile(name, tempmempool, true, &filesize);
8592 if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8593 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8597 cache->skinframe = skinframe;
8600 texture_t *R_GetCurrentTexture(texture_t *t)
8603 const entity_render_t *ent = rsurface.entity;
8604 dp_model_t *model = ent->model;
8605 q3shaderinfo_layer_tcmod_t *tcmod;
8607 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8608 return t->currentframe;
8609 t->update_lastrenderframe = r_textureframe;
8610 t->update_lastrenderentity = (void *)ent;
8612 // switch to an alternate material if this is a q1bsp animated material
8614 texture_t *texture = t;
8615 int s = rsurface.ent_skinnum;
8616 if ((unsigned int)s >= (unsigned int)model->numskins)
8618 if (model->skinscenes)
8620 if (model->skinscenes[s].framecount > 1)
8621 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8623 s = model->skinscenes[s].firstframe;
8626 t = t + s * model->num_surfaces;
8629 // use an alternate animation if the entity's frame is not 0,
8630 // and only if the texture has an alternate animation
8631 if (rsurface.ent_alttextures && t->anim_total[1])
8632 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8634 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8636 texture->currentframe = t;
8639 // update currentskinframe to be a qw skin or animation frame
8640 if (rsurface.ent_qwskin >= 0)
8642 i = rsurface.ent_qwskin;
8643 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8645 r_qwskincache_size = cl.maxclients;
8647 Mem_Free(r_qwskincache);
8648 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8650 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8651 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8652 t->currentskinframe = r_qwskincache[i].skinframe;
8653 if (t->currentskinframe == NULL)
8654 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8656 else if (t->numskinframes >= 2)
8657 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8658 if (t->backgroundnumskinframes >= 2)
8659 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8661 t->currentmaterialflags = t->basematerialflags;
8662 t->currentalpha = rsurface.colormod[3];
8663 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8664 t->currentalpha *= r_wateralpha.value;
8665 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8666 t->currentalpha *= t->r_water_wateralpha;
8667 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8668 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8669 if (!(rsurface.ent_flags & RENDER_LIGHT))
8670 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8671 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8673 // pick a model lighting mode
8674 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8675 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8677 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8679 if (rsurface.ent_flags & RENDER_ADDITIVE)
8680 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8681 else if (t->currentalpha < 1)
8682 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8683 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8684 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8685 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8686 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8687 if (t->backgroundnumskinframes)
8688 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8689 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8691 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8692 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8695 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8696 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8697 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8699 // there is no tcmod
8700 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8702 t->currenttexmatrix = r_waterscrollmatrix;
8703 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8705 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8707 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8708 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8711 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8712 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8713 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8714 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8716 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8717 if (t->currentskinframe->qpixels)
8718 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8719 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8720 if (!t->basetexture)
8721 t->basetexture = r_texture_notexture;
8722 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8723 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8724 t->nmaptexture = t->currentskinframe->nmap;
8725 if (!t->nmaptexture)
8726 t->nmaptexture = r_texture_blanknormalmap;
8727 t->glosstexture = r_texture_black;
8728 t->glowtexture = t->currentskinframe->glow;
8729 t->fogtexture = t->currentskinframe->fog;
8730 if (t->backgroundnumskinframes)
8732 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8733 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8734 t->backgroundglosstexture = r_texture_black;
8735 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8736 if (!t->backgroundnmaptexture)
8737 t->backgroundnmaptexture = r_texture_blanknormalmap;
8741 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8742 t->backgroundnmaptexture = r_texture_blanknormalmap;
8743 t->backgroundglosstexture = r_texture_black;
8744 t->backgroundglowtexture = NULL;
8746 t->specularpower = r_shadow_glossexponent.value;
8747 // TODO: store reference values for these in the texture?
8748 t->specularscale = 0;
8749 if (r_shadow_gloss.integer > 0)
8751 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8753 if (r_shadow_glossintensity.value > 0)
8755 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8756 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8757 t->specularscale = r_shadow_glossintensity.value;
8760 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8762 t->glosstexture = r_texture_white;
8763 t->backgroundglosstexture = r_texture_white;
8764 t->specularscale = r_shadow_gloss2intensity.value;
8765 t->specularpower = r_shadow_gloss2exponent.value;
8768 t->specularscale *= t->specularscalemod;
8769 t->specularpower *= t->specularpowermod;
8771 // lightmaps mode looks bad with dlights using actual texturing, so turn
8772 // off the colormap and glossmap, but leave the normalmap on as it still
8773 // accurately represents the shading involved
8774 if (gl_lightmaps.integer)
8776 t->basetexture = r_texture_grey128;
8777 t->pantstexture = r_texture_black;
8778 t->shirttexture = r_texture_black;
8779 t->nmaptexture = r_texture_blanknormalmap;
8780 t->glosstexture = r_texture_black;
8781 t->glowtexture = NULL;
8782 t->fogtexture = NULL;
8783 t->backgroundbasetexture = NULL;
8784 t->backgroundnmaptexture = r_texture_blanknormalmap;
8785 t->backgroundglosstexture = r_texture_black;
8786 t->backgroundglowtexture = NULL;
8787 t->specularscale = 0;
8788 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8791 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8792 VectorClear(t->dlightcolor);
8793 t->currentnumlayers = 0;
8794 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8796 int blendfunc1, blendfunc2;
8798 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8800 blendfunc1 = GL_SRC_ALPHA;
8801 blendfunc2 = GL_ONE;
8803 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8805 blendfunc1 = GL_SRC_ALPHA;
8806 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8808 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8810 blendfunc1 = t->customblendfunc[0];
8811 blendfunc2 = t->customblendfunc[1];
8815 blendfunc1 = GL_ONE;
8816 blendfunc2 = GL_ZERO;
8818 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8819 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8821 // fullbright is not affected by r_refdef.lightmapintensity
8822 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]);
8823 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8824 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]);
8825 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8826 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]);
8830 vec3_t ambientcolor;
8832 // set the color tint used for lights affecting this surface
8833 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8835 // q3bsp has no lightmap updates, so the lightstylevalue that
8836 // would normally be baked into the lightmap must be
8837 // applied to the color
8838 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8839 if (model->type == mod_brushq3)
8840 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8841 colorscale *= r_refdef.lightmapintensity;
8842 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8843 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8844 // basic lit geometry
8845 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]);
8846 // add pants/shirt if needed
8847 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8848 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]);
8849 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8850 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]);
8851 // now add ambient passes if needed
8852 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8854 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]);
8855 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8856 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]);
8857 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8858 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]);
8861 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8862 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]);
8863 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8865 // if this is opaque use alpha blend which will darken the earlier
8868 // if this is an alpha blended material, all the earlier passes
8869 // were darkened by fog already, so we only need to add the fog
8870 // color ontop through the fog mask texture
8872 // if this is an additive blended material, all the earlier passes
8873 // were darkened by fog already, and we should not add fog color
8874 // (because the background was not darkened, there is no fog color
8875 // that was lost behind it).
8876 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]);
8880 return t->currentframe;
8883 rsurfacestate_t rsurface;
8885 void R_Mesh_ResizeArrays(int newvertices)
8888 if (rsurface.array_size >= newvertices)
8890 if (rsurface.array_modelvertex3f)
8891 Mem_Free(rsurface.array_modelvertex3f);
8892 rsurface.array_size = (newvertices + 1023) & ~1023;
8893 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8894 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
8895 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
8896 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
8897 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
8898 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
8899 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8900 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8901 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
8902 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
8903 rsurface.array_color4f = base + rsurface.array_size * 27;
8904 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8907 void RSurf_ActiveWorldEntity(void)
8909 dp_model_t *model = r_refdef.scene.worldmodel;
8910 //if (rsurface.entity == r_refdef.scene.worldentity)
8912 rsurface.entity = r_refdef.scene.worldentity;
8913 rsurface.skeleton = NULL;
8914 rsurface.ent_skinnum = 0;
8915 rsurface.ent_qwskin = -1;
8916 rsurface.ent_shadertime = 0;
8917 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8918 if (rsurface.array_size < model->surfmesh.num_vertices)
8919 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8920 rsurface.matrix = identitymatrix;
8921 rsurface.inversematrix = identitymatrix;
8922 rsurface.matrixscale = 1;
8923 rsurface.inversematrixscale = 1;
8924 R_EntityMatrix(&identitymatrix);
8925 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8926 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8927 rsurface.fograngerecip = r_refdef.fograngerecip;
8928 rsurface.fogheightfade = r_refdef.fogheightfade;
8929 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8930 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8931 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8932 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8933 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8934 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8935 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8936 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8937 rsurface.colormod[3] = 1;
8938 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);
8939 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8940 rsurface.frameblend[0].lerp = 1;
8941 rsurface.ent_alttextures = false;
8942 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8943 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8944 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8945 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8946 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8947 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8948 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8949 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8950 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8951 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8952 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8953 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8954 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8955 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8956 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8957 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8958 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8959 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8960 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8961 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8962 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8963 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8964 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8965 rsurface.modelelement3i = model->surfmesh.data_element3i;
8966 rsurface.modelelement3s = model->surfmesh.data_element3s;
8967 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8968 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8969 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8970 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8971 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8972 rsurface.modelsurfaces = model->data_surfaces;
8973 rsurface.generatedvertex = false;
8974 rsurface.vertex3f = rsurface.modelvertex3f;
8975 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8976 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8977 rsurface.svector3f = rsurface.modelsvector3f;
8978 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8979 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8980 rsurface.tvector3f = rsurface.modeltvector3f;
8981 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8982 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8983 rsurface.normal3f = rsurface.modelnormal3f;
8984 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8985 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8986 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8989 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8991 dp_model_t *model = ent->model;
8992 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8994 rsurface.entity = (entity_render_t *)ent;
8995 rsurface.skeleton = ent->skeleton;
8996 rsurface.ent_skinnum = ent->skinnum;
8997 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;
8998 rsurface.ent_shadertime = ent->shadertime;
8999 rsurface.ent_flags = ent->flags;
9000 if (rsurface.array_size < model->surfmesh.num_vertices)
9001 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9002 rsurface.matrix = ent->matrix;
9003 rsurface.inversematrix = ent->inversematrix;
9004 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9005 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9006 R_EntityMatrix(&rsurface.matrix);
9007 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9008 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9009 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9010 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9011 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9012 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9013 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9014 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9015 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9016 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9017 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9018 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9019 rsurface.colormod[3] = ent->alpha;
9020 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9021 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9022 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9023 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9024 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9025 if (ent->model->brush.submodel && !prepass)
9027 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9028 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9030 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9032 if (ent->animcache_vertex3f && !r_framedata_failed)
9034 rsurface.modelvertex3f = ent->animcache_vertex3f;
9035 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9036 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9037 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9039 else if (wanttangents)
9041 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9042 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9043 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9044 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9045 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9047 else if (wantnormals)
9049 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9050 rsurface.modelsvector3f = NULL;
9051 rsurface.modeltvector3f = NULL;
9052 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9053 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9057 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9058 rsurface.modelsvector3f = NULL;
9059 rsurface.modeltvector3f = NULL;
9060 rsurface.modelnormal3f = NULL;
9061 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9063 rsurface.modelvertex3f_bufferobject = 0;
9064 rsurface.modelvertex3f_bufferoffset = 0;
9065 rsurface.modelsvector3f_bufferobject = 0;
9066 rsurface.modelsvector3f_bufferoffset = 0;
9067 rsurface.modeltvector3f_bufferobject = 0;
9068 rsurface.modeltvector3f_bufferoffset = 0;
9069 rsurface.modelnormal3f_bufferobject = 0;
9070 rsurface.modelnormal3f_bufferoffset = 0;
9071 rsurface.generatedvertex = true;
9075 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9076 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9077 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9078 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9079 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9080 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9081 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9082 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9083 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9084 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9085 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9086 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9087 rsurface.generatedvertex = false;
9089 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9090 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9091 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9092 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9093 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9094 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9095 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9096 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9097 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9098 rsurface.modelelement3i = model->surfmesh.data_element3i;
9099 rsurface.modelelement3s = model->surfmesh.data_element3s;
9100 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9101 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9102 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9103 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9104 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9105 rsurface.modelsurfaces = model->data_surfaces;
9106 rsurface.vertex3f = rsurface.modelvertex3f;
9107 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9108 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9109 rsurface.svector3f = rsurface.modelsvector3f;
9110 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9111 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9112 rsurface.tvector3f = rsurface.modeltvector3f;
9113 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9114 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9115 rsurface.normal3f = rsurface.modelnormal3f;
9116 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9117 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9118 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9121 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)
9123 rsurface.entity = r_refdef.scene.worldentity;
9124 rsurface.skeleton = NULL;
9125 rsurface.ent_skinnum = 0;
9126 rsurface.ent_qwskin = -1;
9127 rsurface.ent_shadertime = shadertime;
9128 rsurface.ent_flags = entflags;
9129 rsurface.modelnum_vertices = numvertices;
9130 rsurface.modelnum_triangles = numtriangles;
9131 if (rsurface.array_size < rsurface.modelnum_vertices)
9132 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9133 rsurface.matrix = *matrix;
9134 rsurface.inversematrix = *inversematrix;
9135 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9136 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9137 R_EntityMatrix(&rsurface.matrix);
9138 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9139 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9140 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9141 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9142 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9143 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9144 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9145 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9146 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9147 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9148 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9149 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9150 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);
9151 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9152 rsurface.frameblend[0].lerp = 1;
9153 rsurface.ent_alttextures = false;
9154 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9155 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9158 rsurface.modelvertex3f = vertex3f;
9159 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9160 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9161 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9163 else if (wantnormals)
9165 rsurface.modelvertex3f = vertex3f;
9166 rsurface.modelsvector3f = NULL;
9167 rsurface.modeltvector3f = NULL;
9168 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9172 rsurface.modelvertex3f = vertex3f;
9173 rsurface.modelsvector3f = NULL;
9174 rsurface.modeltvector3f = NULL;
9175 rsurface.modelnormal3f = NULL;
9177 rsurface.modelvertex3f_bufferobject = 0;
9178 rsurface.modelvertex3f_bufferoffset = 0;
9179 rsurface.modelsvector3f_bufferobject = 0;
9180 rsurface.modelsvector3f_bufferoffset = 0;
9181 rsurface.modeltvector3f_bufferobject = 0;
9182 rsurface.modeltvector3f_bufferoffset = 0;
9183 rsurface.modelnormal3f_bufferobject = 0;
9184 rsurface.modelnormal3f_bufferoffset = 0;
9185 rsurface.generatedvertex = true;
9186 rsurface.modellightmapcolor4f = color4f;
9187 rsurface.modellightmapcolor4f_bufferobject = 0;
9188 rsurface.modellightmapcolor4f_bufferoffset = 0;
9189 rsurface.modeltexcoordtexture2f = texcoord2f;
9190 rsurface.modeltexcoordtexture2f_bufferobject = 0;
9191 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9192 rsurface.modeltexcoordlightmap2f = NULL;
9193 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9194 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9195 rsurface.modelelement3i = element3i;
9196 rsurface.modelelement3s = element3s;
9197 rsurface.modelelement3i_bufferobject = 0;
9198 rsurface.modelelement3s_bufferobject = 0;
9199 rsurface.modellightmapoffsets = NULL;
9200 rsurface.modelsurfaces = NULL;
9201 rsurface.vertex3f = rsurface.modelvertex3f;
9202 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9203 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9204 rsurface.svector3f = rsurface.modelsvector3f;
9205 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9206 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9207 rsurface.tvector3f = rsurface.modeltvector3f;
9208 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9209 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9210 rsurface.normal3f = rsurface.modelnormal3f;
9211 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9212 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9213 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9215 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9217 if ((wantnormals || wanttangents) && !normal3f)
9218 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9219 if (wanttangents && !svector3f)
9220 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);
9224 float RSurf_FogPoint(const float *v)
9226 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9227 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9228 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9229 float FogHeightFade = r_refdef.fogheightfade;
9231 unsigned int fogmasktableindex;
9232 if (r_refdef.fogplaneviewabove)
9233 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9235 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9236 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9237 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9240 float RSurf_FogVertex(const float *v)
9242 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9243 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9244 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9245 float FogHeightFade = rsurface.fogheightfade;
9247 unsigned int fogmasktableindex;
9248 if (r_refdef.fogplaneviewabove)
9249 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9251 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9252 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9253 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9256 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9257 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9260 int texturesurfaceindex;
9265 const float *v1, *in_tc;
9267 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9269 q3shaderinfo_deform_t *deform;
9270 // 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
9271 if (rsurface.generatedvertex)
9273 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9274 generatenormals = true;
9275 for (i = 0;i < Q3MAXDEFORMS;i++)
9277 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9279 generatetangents = true;
9280 generatenormals = true;
9282 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9283 generatenormals = true;
9285 if (generatenormals && !rsurface.modelnormal3f)
9287 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9288 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9289 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9290 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9292 if (generatetangents && !rsurface.modelsvector3f)
9294 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9295 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9296 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9297 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9298 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9299 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9300 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);
9303 rsurface.vertex3f = rsurface.modelvertex3f;
9304 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9305 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9306 rsurface.svector3f = rsurface.modelsvector3f;
9307 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9308 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9309 rsurface.tvector3f = rsurface.modeltvector3f;
9310 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9311 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9312 rsurface.normal3f = rsurface.modelnormal3f;
9313 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9314 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9315 // if vertices are deformed (sprite flares and things in maps, possibly
9316 // water waves, bulges and other deformations), generate them into
9317 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9318 // (may be static model data or generated data for an animated model, or
9319 // the previous deform pass)
9320 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9322 switch (deform->deform)
9325 case Q3DEFORM_PROJECTIONSHADOW:
9326 case Q3DEFORM_TEXT0:
9327 case Q3DEFORM_TEXT1:
9328 case Q3DEFORM_TEXT2:
9329 case Q3DEFORM_TEXT3:
9330 case Q3DEFORM_TEXT4:
9331 case Q3DEFORM_TEXT5:
9332 case Q3DEFORM_TEXT6:
9333 case Q3DEFORM_TEXT7:
9336 case Q3DEFORM_AUTOSPRITE:
9337 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9338 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9339 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9340 VectorNormalize(newforward);
9341 VectorNormalize(newright);
9342 VectorNormalize(newup);
9343 // make deformed versions of only the model vertices used by the specified surfaces
9344 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9346 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9347 // a single autosprite surface can contain multiple sprites...
9348 for (j = 0;j < surface->num_vertices - 3;j += 4)
9350 VectorClear(center);
9351 for (i = 0;i < 4;i++)
9352 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9353 VectorScale(center, 0.25f, center);
9354 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9355 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9356 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9357 for (i = 0;i < 4;i++)
9359 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9360 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9363 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);
9364 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);
9366 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9367 rsurface.vertex3f_bufferobject = 0;
9368 rsurface.vertex3f_bufferoffset = 0;
9369 rsurface.svector3f = rsurface.array_deformedsvector3f;
9370 rsurface.svector3f_bufferobject = 0;
9371 rsurface.svector3f_bufferoffset = 0;
9372 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9373 rsurface.tvector3f_bufferobject = 0;
9374 rsurface.tvector3f_bufferoffset = 0;
9375 rsurface.normal3f = rsurface.array_deformednormal3f;
9376 rsurface.normal3f_bufferobject = 0;
9377 rsurface.normal3f_bufferoffset = 0;
9379 case Q3DEFORM_AUTOSPRITE2:
9380 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9381 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9382 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9383 VectorNormalize(newforward);
9384 VectorNormalize(newright);
9385 VectorNormalize(newup);
9386 // make deformed versions of only the model vertices used by the specified surfaces
9387 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9389 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9390 const float *v1, *v2;
9400 memset(shortest, 0, sizeof(shortest));
9401 // a single autosprite surface can contain multiple sprites...
9402 for (j = 0;j < surface->num_vertices - 3;j += 4)
9404 VectorClear(center);
9405 for (i = 0;i < 4;i++)
9406 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9407 VectorScale(center, 0.25f, center);
9408 // find the two shortest edges, then use them to define the
9409 // axis vectors for rotating around the central axis
9410 for (i = 0;i < 6;i++)
9412 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9413 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9415 Debug_PolygonBegin(NULL, 0);
9416 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9417 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);
9418 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9421 l = VectorDistance2(v1, v2);
9422 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9424 l += (1.0f / 1024.0f);
9425 if (shortest[0].length2 > l || i == 0)
9427 shortest[1] = shortest[0];
9428 shortest[0].length2 = l;
9429 shortest[0].v1 = v1;
9430 shortest[0].v2 = v2;
9432 else if (shortest[1].length2 > l || i == 1)
9434 shortest[1].length2 = l;
9435 shortest[1].v1 = v1;
9436 shortest[1].v2 = v2;
9439 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9440 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9442 Debug_PolygonBegin(NULL, 0);
9443 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9444 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);
9445 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9448 // this calculates the right vector from the shortest edge
9449 // and the up vector from the edge midpoints
9450 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9451 VectorNormalize(right);
9452 VectorSubtract(end, start, up);
9453 VectorNormalize(up);
9454 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9455 VectorSubtract(rsurface.localvieworigin, center, forward);
9456 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9457 VectorNegate(forward, forward);
9458 VectorReflect(forward, 0, up, forward);
9459 VectorNormalize(forward);
9460 CrossProduct(up, forward, newright);
9461 VectorNormalize(newright);
9463 Debug_PolygonBegin(NULL, 0);
9464 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);
9465 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9466 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9470 Debug_PolygonBegin(NULL, 0);
9471 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9472 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9473 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9476 // rotate the quad around the up axis vector, this is made
9477 // especially easy by the fact we know the quad is flat,
9478 // so we only have to subtract the center position and
9479 // measure distance along the right vector, and then
9480 // multiply that by the newright vector and add back the
9482 // we also need to subtract the old position to undo the
9483 // displacement from the center, which we do with a
9484 // DotProduct, the subtraction/addition of center is also
9485 // optimized into DotProducts here
9486 l = DotProduct(right, center);
9487 for (i = 0;i < 4;i++)
9489 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9490 f = DotProduct(right, v1) - l;
9491 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9494 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);
9495 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);
9497 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9498 rsurface.vertex3f_bufferobject = 0;
9499 rsurface.vertex3f_bufferoffset = 0;
9500 rsurface.svector3f = rsurface.array_deformedsvector3f;
9501 rsurface.svector3f_bufferobject = 0;
9502 rsurface.svector3f_bufferoffset = 0;
9503 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9504 rsurface.tvector3f_bufferobject = 0;
9505 rsurface.tvector3f_bufferoffset = 0;
9506 rsurface.normal3f = rsurface.array_deformednormal3f;
9507 rsurface.normal3f_bufferobject = 0;
9508 rsurface.normal3f_bufferoffset = 0;
9510 case Q3DEFORM_NORMAL:
9511 // deform the normals to make reflections wavey
9512 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9514 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9515 for (j = 0;j < surface->num_vertices;j++)
9518 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9519 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9520 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9521 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9522 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9523 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9524 VectorNormalize(normal);
9526 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);
9528 rsurface.svector3f = rsurface.array_deformedsvector3f;
9529 rsurface.svector3f_bufferobject = 0;
9530 rsurface.svector3f_bufferoffset = 0;
9531 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9532 rsurface.tvector3f_bufferobject = 0;
9533 rsurface.tvector3f_bufferoffset = 0;
9534 rsurface.normal3f = rsurface.array_deformednormal3f;
9535 rsurface.normal3f_bufferobject = 0;
9536 rsurface.normal3f_bufferoffset = 0;
9539 // deform vertex array to make wavey water and flags and such
9540 waveparms[0] = deform->waveparms[0];
9541 waveparms[1] = deform->waveparms[1];
9542 waveparms[2] = deform->waveparms[2];
9543 waveparms[3] = deform->waveparms[3];
9544 // this is how a divisor of vertex influence on deformation
9545 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9546 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9547 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9549 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9550 for (j = 0;j < surface->num_vertices;j++)
9552 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9553 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9554 // if the wavefunc depends on time, evaluate it per-vertex
9557 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9558 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9560 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9563 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9564 rsurface.vertex3f_bufferobject = 0;
9565 rsurface.vertex3f_bufferoffset = 0;
9567 case Q3DEFORM_BULGE:
9568 // deform vertex array to make the surface have moving bulges
9569 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9571 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9572 for (j = 0;j < surface->num_vertices;j++)
9574 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9575 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9578 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9579 rsurface.vertex3f_bufferobject = 0;
9580 rsurface.vertex3f_bufferoffset = 0;
9583 // deform vertex array
9584 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9585 VectorScale(deform->parms, scale, waveparms);
9586 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9588 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9589 for (j = 0;j < surface->num_vertices;j++)
9590 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9592 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9593 rsurface.vertex3f_bufferobject = 0;
9594 rsurface.vertex3f_bufferoffset = 0;
9598 // generate texcoords based on the chosen texcoord source
9599 switch(rsurface.texture->tcgen.tcgen)
9602 case Q3TCGEN_TEXTURE:
9603 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9604 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
9605 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9607 case Q3TCGEN_LIGHTMAP:
9608 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
9609 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9610 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9612 case Q3TCGEN_VECTOR:
9613 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9615 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9616 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)
9618 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9619 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9622 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9623 rsurface.texcoordtexture2f_bufferobject = 0;
9624 rsurface.texcoordtexture2f_bufferoffset = 0;
9626 case Q3TCGEN_ENVIRONMENT:
9627 // make environment reflections using a spheremap
9628 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9630 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9631 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9632 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9633 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9634 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9636 // identical to Q3A's method, but executed in worldspace so
9637 // carried models can be shiny too
9639 float viewer[3], d, reflected[3], worldreflected[3];
9641 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9642 // VectorNormalize(viewer);
9644 d = DotProduct(normal, viewer);
9646 reflected[0] = normal[0]*2*d - viewer[0];
9647 reflected[1] = normal[1]*2*d - viewer[1];
9648 reflected[2] = normal[2]*2*d - viewer[2];
9649 // note: this is proportinal to viewer, so we can normalize later
9651 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9652 VectorNormalize(worldreflected);
9654 // note: this sphere map only uses world x and z!
9655 // so positive and negative y will LOOK THE SAME.
9656 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9657 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9660 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9661 rsurface.texcoordtexture2f_bufferobject = 0;
9662 rsurface.texcoordtexture2f_bufferoffset = 0;
9665 // the only tcmod that needs software vertex processing is turbulent, so
9666 // check for it here and apply the changes if needed
9667 // and we only support that as the first one
9668 // (handling a mixture of turbulent and other tcmods would be problematic
9669 // without punting it entirely to a software path)
9670 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9672 amplitude = rsurface.texture->tcmods[0].parms[1];
9673 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9674 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9676 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9677 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)
9679 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9680 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9683 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9684 rsurface.texcoordtexture2f_bufferobject = 0;
9685 rsurface.texcoordtexture2f_bufferoffset = 0;
9687 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9688 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9689 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9690 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9693 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9696 const msurface_t *surface = texturesurfacelist[0];
9697 const msurface_t *surface2;
9702 // TODO: lock all array ranges before render, rather than on each surface
9703 if (texturenumsurfaces == 1)
9704 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);
9705 else if (r_batchmode.integer == 2)
9707 #define MAXBATCHTRIANGLES 4096
9708 int batchtriangles = 0;
9709 static int batchelements[MAXBATCHTRIANGLES*3];
9710 for (i = 0;i < texturenumsurfaces;i = j)
9712 surface = texturesurfacelist[i];
9714 if (surface->num_triangles > MAXBATCHTRIANGLES)
9716 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);
9719 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9720 batchtriangles = surface->num_triangles;
9721 firstvertex = surface->num_firstvertex;
9722 endvertex = surface->num_firstvertex + surface->num_vertices;
9723 for (;j < texturenumsurfaces;j++)
9725 surface2 = texturesurfacelist[j];
9726 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9728 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9729 batchtriangles += surface2->num_triangles;
9730 firstvertex = min(firstvertex, surface2->num_firstvertex);
9731 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9733 surface2 = texturesurfacelist[j-1];
9734 numvertices = endvertex - firstvertex;
9735 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9738 else if (r_batchmode.integer == 1)
9740 for (i = 0;i < texturenumsurfaces;i = j)
9742 surface = texturesurfacelist[i];
9743 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9744 if (texturesurfacelist[j] != surface2)
9746 surface2 = texturesurfacelist[j-1];
9747 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9748 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9749 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9754 for (i = 0;i < texturenumsurfaces;i++)
9756 surface = texturesurfacelist[i];
9757 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);
9762 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9764 switch(vid.renderpath)
9766 case RENDERPATH_CGGL:
9768 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9769 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9772 case RENDERPATH_GL20:
9773 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9774 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9776 case RENDERPATH_GL13:
9777 case RENDERPATH_GL11:
9778 R_Mesh_TexBind(0, surface->lightmaptexture);
9783 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9785 // pick the closest matching water plane and bind textures
9786 int planeindex, vertexindex;
9790 r_waterstate_waterplane_t *p, *bestp;
9793 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9796 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9798 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9799 d += fabs(PlaneDiff(vert, &p->plane));
9801 if (bestd > d || !bestp)
9807 switch(vid.renderpath)
9809 case RENDERPATH_CGGL:
9811 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9812 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9815 case RENDERPATH_GL20:
9816 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9817 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9819 case RENDERPATH_GL13:
9820 case RENDERPATH_GL11:
9825 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9828 const msurface_t *surface;
9829 if (r_waterstate.renderingscene)
9831 for (i = 0;i < texturenumsurfaces;i++)
9833 surface = texturesurfacelist[i];
9834 RSurf_BindLightmapForSurface(surface);
9835 RSurf_BindReflectionForSurface(surface);
9836 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);
9840 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9844 const msurface_t *surface = texturesurfacelist[0];
9845 const msurface_t *surface2;
9850 if (texturenumsurfaces == 1)
9852 RSurf_BindLightmapForSurface(surface);
9853 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);
9855 else if (r_batchmode.integer == 2)
9857 #define MAXBATCHTRIANGLES 4096
9858 int batchtriangles = 0;
9859 static int batchelements[MAXBATCHTRIANGLES*3];
9860 for (i = 0;i < texturenumsurfaces;i = j)
9862 surface = texturesurfacelist[i];
9863 RSurf_BindLightmapForSurface(surface);
9865 if (surface->num_triangles > MAXBATCHTRIANGLES)
9867 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);
9870 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9871 batchtriangles = surface->num_triangles;
9872 firstvertex = surface->num_firstvertex;
9873 endvertex = surface->num_firstvertex + surface->num_vertices;
9874 for (;j < texturenumsurfaces;j++)
9876 surface2 = texturesurfacelist[j];
9877 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9879 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9880 batchtriangles += surface2->num_triangles;
9881 firstvertex = min(firstvertex, surface2->num_firstvertex);
9882 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9884 surface2 = texturesurfacelist[j-1];
9885 numvertices = endvertex - firstvertex;
9886 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9889 else if (r_batchmode.integer == 1)
9892 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9893 for (i = 0;i < texturenumsurfaces;i = j)
9895 surface = texturesurfacelist[i];
9896 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9897 if (texturesurfacelist[j] != surface2)
9899 Con_Printf(" %i", j - i);
9902 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9904 for (i = 0;i < texturenumsurfaces;i = j)
9906 surface = texturesurfacelist[i];
9907 RSurf_BindLightmapForSurface(surface);
9908 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9909 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9912 Con_Printf(" %i", j - i);
9914 surface2 = texturesurfacelist[j-1];
9915 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9916 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9917 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9925 for (i = 0;i < texturenumsurfaces;i++)
9927 surface = texturesurfacelist[i];
9928 RSurf_BindLightmapForSurface(surface);
9929 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);
9934 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9937 int texturesurfaceindex;
9938 if (r_showsurfaces.integer == 2)
9940 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9942 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9943 for (j = 0;j < surface->num_triangles;j++)
9945 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9946 GL_Color(f, f, f, 1);
9947 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9953 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9955 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9956 int k = (int)(((size_t)surface) / sizeof(msurface_t));
9957 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);
9958 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);
9963 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9965 int texturesurfaceindex;
9969 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9971 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9972 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)
9980 rsurface.lightmapcolor4f = rsurface.array_color4f;
9981 rsurface.lightmapcolor4f_bufferobject = 0;
9982 rsurface.lightmapcolor4f_bufferoffset = 0;
9985 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9987 int texturesurfaceindex;
9993 if (rsurface.lightmapcolor4f)
9995 // generate color arrays for the surfaces in this list
9996 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9998 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9999 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)
10001 f = RSurf_FogVertex(v);
10011 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10013 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10014 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)
10016 f = RSurf_FogVertex(v);
10024 rsurface.lightmapcolor4f = rsurface.array_color4f;
10025 rsurface.lightmapcolor4f_bufferobject = 0;
10026 rsurface.lightmapcolor4f_bufferoffset = 0;
10029 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10031 int texturesurfaceindex;
10037 if (!rsurface.lightmapcolor4f)
10039 // generate color arrays for the surfaces in this list
10040 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10042 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10043 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)
10045 f = RSurf_FogVertex(v);
10046 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10047 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10048 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10052 rsurface.lightmapcolor4f = rsurface.array_color4f;
10053 rsurface.lightmapcolor4f_bufferobject = 0;
10054 rsurface.lightmapcolor4f_bufferoffset = 0;
10057 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10059 int texturesurfaceindex;
10063 if (!rsurface.lightmapcolor4f)
10065 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10067 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10068 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)
10076 rsurface.lightmapcolor4f = rsurface.array_color4f;
10077 rsurface.lightmapcolor4f_bufferobject = 0;
10078 rsurface.lightmapcolor4f_bufferoffset = 0;
10081 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10083 int texturesurfaceindex;
10087 if (!rsurface.lightmapcolor4f)
10089 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10091 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10092 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)
10094 c2[0] = c[0] + r_refdef.scene.ambient;
10095 c2[1] = c[1] + r_refdef.scene.ambient;
10096 c2[2] = c[2] + r_refdef.scene.ambient;
10100 rsurface.lightmapcolor4f = rsurface.array_color4f;
10101 rsurface.lightmapcolor4f_bufferobject = 0;
10102 rsurface.lightmapcolor4f_bufferoffset = 0;
10105 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10108 rsurface.lightmapcolor4f = NULL;
10109 rsurface.lightmapcolor4f_bufferobject = 0;
10110 rsurface.lightmapcolor4f_bufferoffset = 0;
10111 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10112 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10113 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10114 GL_Color(r, g, b, a);
10115 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10118 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10120 // TODO: optimize applyfog && applycolor case
10121 // just apply fog if necessary, and tint the fog color array if necessary
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_Simple(texturenumsurfaces, texturesurfacelist);
10132 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10134 int texturesurfaceindex;
10138 if (texturesurfacelist[0]->lightmapinfo)
10140 // generate color arrays for the surfaces in this list
10141 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10143 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10144 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10146 if (surface->lightmapinfo->samples)
10148 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10149 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10150 VectorScale(lm, scale, c);
10151 if (surface->lightmapinfo->styles[1] != 255)
10153 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10155 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10156 VectorMA(c, scale, lm, c);
10157 if (surface->lightmapinfo->styles[2] != 255)
10160 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10161 VectorMA(c, scale, lm, c);
10162 if (surface->lightmapinfo->styles[3] != 255)
10165 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10166 VectorMA(c, scale, lm, c);
10176 rsurface.lightmapcolor4f = rsurface.array_color4f;
10177 rsurface.lightmapcolor4f_bufferobject = 0;
10178 rsurface.lightmapcolor4f_bufferoffset = 0;
10182 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10183 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10184 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10186 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10187 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10188 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10189 GL_Color(r, g, b, a);
10190 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10193 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10195 int texturesurfaceindex;
10202 vec3_t ambientcolor;
10203 vec3_t diffusecolor;
10207 VectorCopy(rsurface.modellight_lightdir, lightdir);
10208 f = 0.5f * r_refdef.lightmapintensity;
10209 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10210 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10211 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10212 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10213 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10214 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10216 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10218 // generate color arrays for the surfaces in this list
10219 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10221 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10222 int numverts = surface->num_vertices;
10223 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10224 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10225 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10226 // q3-style directional shading
10227 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10229 if ((f = DotProduct(n, lightdir)) > 0)
10230 VectorMA(ambientcolor, f, diffusecolor, c);
10232 VectorCopy(ambientcolor, c);
10240 rsurface.lightmapcolor4f = rsurface.array_color4f;
10241 rsurface.lightmapcolor4f_bufferobject = 0;
10242 rsurface.lightmapcolor4f_bufferoffset = 0;
10243 *applycolor = false;
10247 *r = ambientcolor[0];
10248 *g = ambientcolor[1];
10249 *b = ambientcolor[2];
10250 rsurface.lightmapcolor4f = NULL;
10251 rsurface.lightmapcolor4f_bufferobject = 0;
10252 rsurface.lightmapcolor4f_bufferoffset = 0;
10256 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10258 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10259 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10260 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10261 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10262 GL_Color(r, g, b, a);
10263 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10266 void RSurf_SetupDepthAndCulling(void)
10268 // submodels are biased to avoid z-fighting with world surfaces that they
10269 // may be exactly overlapping (avoids z-fighting artifacts on certain
10270 // doors and things in Quake maps)
10271 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10272 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10273 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10274 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10277 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10279 // transparent sky would be ridiculous
10280 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10282 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10283 skyrenderlater = true;
10284 RSurf_SetupDepthAndCulling();
10285 GL_DepthMask(true);
10286 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10287 // skymasking on them, and Quake3 never did sky masking (unlike
10288 // software Quake and software Quake2), so disable the sky masking
10289 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10290 // and skymasking also looks very bad when noclipping outside the
10291 // level, so don't use it then either.
10292 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10294 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10295 R_Mesh_ColorPointer(NULL, 0, 0);
10296 R_Mesh_ResetTextureState();
10297 if (skyrendermasked)
10299 R_SetupShader_DepthOrShadow();
10300 // depth-only (masking)
10301 GL_ColorMask(0,0,0,0);
10302 // just to make sure that braindead drivers don't draw
10303 // anything despite that colormask...
10304 GL_BlendFunc(GL_ZERO, GL_ONE);
10308 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10310 GL_BlendFunc(GL_ONE, GL_ZERO);
10312 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10313 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10314 if (skyrendermasked)
10315 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10317 R_Mesh_ResetTextureState();
10318 GL_Color(1, 1, 1, 1);
10321 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10322 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10323 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10325 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10328 // render screenspace normalmap to texture
10329 GL_DepthMask(true);
10330 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10331 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10333 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10335 // render water or distortion background, then blend surface on top
10336 GL_DepthMask(true);
10337 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10338 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10339 GL_DepthMask(false);
10340 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10341 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10345 // render surface normally
10346 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10347 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10348 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10349 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10350 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10351 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10353 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10357 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10359 // OpenGL 1.3 path - anything not completely ancient
10360 int texturesurfaceindex;
10361 qboolean applycolor;
10364 const texturelayer_t *layer;
10365 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10367 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10370 int layertexrgbscale;
10371 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10373 if (layerindex == 0)
10374 GL_AlphaTest(true);
10377 GL_AlphaTest(false);
10378 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10381 GL_DepthMask(layer->depthmask && writedepth);
10382 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10383 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10385 layertexrgbscale = 4;
10386 VectorScale(layer->color, 0.25f, layercolor);
10388 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10390 layertexrgbscale = 2;
10391 VectorScale(layer->color, 0.5f, layercolor);
10395 layertexrgbscale = 1;
10396 VectorScale(layer->color, 1.0f, layercolor);
10398 layercolor[3] = layer->color[3];
10399 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10400 R_Mesh_ColorPointer(NULL, 0, 0);
10401 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10402 switch (layer->type)
10404 case TEXTURELAYERTYPE_LITTEXTURE:
10405 // single-pass lightmapped texture with 2x rgbscale
10406 R_Mesh_TexBind(0, r_texture_white);
10407 R_Mesh_TexMatrix(0, NULL);
10408 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10409 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10410 R_Mesh_TexBind(1, layer->texture);
10411 R_Mesh_TexMatrix(1, &layer->texmatrix);
10412 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10413 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10414 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10415 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10416 else if (rsurface.uselightmaptexture)
10417 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10419 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10421 case TEXTURELAYERTYPE_TEXTURE:
10422 // singletexture unlit texture with transparency support
10423 R_Mesh_TexBind(0, layer->texture);
10424 R_Mesh_TexMatrix(0, &layer->texmatrix);
10425 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10426 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10427 R_Mesh_TexBind(1, 0);
10428 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10429 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10431 case TEXTURELAYERTYPE_FOG:
10432 // singletexture fogging
10433 if (layer->texture)
10435 R_Mesh_TexBind(0, layer->texture);
10436 R_Mesh_TexMatrix(0, &layer->texmatrix);
10437 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10438 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10442 R_Mesh_TexBind(0, 0);
10443 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10445 R_Mesh_TexBind(1, 0);
10446 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10447 // generate a color array for the fog pass
10448 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10449 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10455 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10456 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)
10458 f = 1 - RSurf_FogVertex(v);
10459 c[0] = layercolor[0];
10460 c[1] = layercolor[1];
10461 c[2] = layercolor[2];
10462 c[3] = f * layercolor[3];
10465 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10468 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10472 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10474 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10475 GL_AlphaTest(false);
10479 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10481 // OpenGL 1.1 - crusty old voodoo path
10482 int texturesurfaceindex;
10485 const texturelayer_t *layer;
10486 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10488 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10490 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10492 if (layerindex == 0)
10493 GL_AlphaTest(true);
10496 GL_AlphaTest(false);
10497 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10500 GL_DepthMask(layer->depthmask && writedepth);
10501 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10502 R_Mesh_ColorPointer(NULL, 0, 0);
10503 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10504 switch (layer->type)
10506 case TEXTURELAYERTYPE_LITTEXTURE:
10507 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10509 // two-pass lit texture with 2x rgbscale
10510 // first the lightmap pass
10511 R_Mesh_TexBind(0, r_texture_white);
10512 R_Mesh_TexMatrix(0, NULL);
10513 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10514 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10515 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10516 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10517 else if (rsurface.uselightmaptexture)
10518 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10520 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10521 // then apply the texture to it
10522 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10523 R_Mesh_TexBind(0, layer->texture);
10524 R_Mesh_TexMatrix(0, &layer->texmatrix);
10525 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10526 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10527 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);
10531 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10532 R_Mesh_TexBind(0, layer->texture);
10533 R_Mesh_TexMatrix(0, &layer->texmatrix);
10534 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10535 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10536 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10537 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);
10539 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);
10542 case TEXTURELAYERTYPE_TEXTURE:
10543 // singletexture unlit texture with transparency support
10544 R_Mesh_TexBind(0, layer->texture);
10545 R_Mesh_TexMatrix(0, &layer->texmatrix);
10546 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10547 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10548 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);
10550 case TEXTURELAYERTYPE_FOG:
10551 // singletexture fogging
10552 if (layer->texture)
10554 R_Mesh_TexBind(0, layer->texture);
10555 R_Mesh_TexMatrix(0, &layer->texmatrix);
10556 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10557 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10561 R_Mesh_TexBind(0, 0);
10562 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10564 // generate a color array for the fog pass
10565 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10566 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10572 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10573 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)
10575 f = 1 - RSurf_FogVertex(v);
10576 c[0] = layer->color[0];
10577 c[1] = layer->color[1];
10578 c[2] = layer->color[2];
10579 c[3] = f * layer->color[3];
10582 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10585 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10589 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10591 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10592 GL_AlphaTest(false);
10596 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10600 GL_AlphaTest(false);
10601 R_Mesh_ColorPointer(NULL, 0, 0);
10602 R_Mesh_ResetTextureState();
10603 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10605 if(rsurface.texture && rsurface.texture->currentskinframe)
10607 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10608 c[3] *= rsurface.texture->currentalpha;
10618 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10620 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10621 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10622 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10625 // brighten it up (as texture value 127 means "unlit")
10626 c[0] *= 2 * r_refdef.view.colorscale;
10627 c[1] *= 2 * r_refdef.view.colorscale;
10628 c[2] *= 2 * r_refdef.view.colorscale;
10630 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10631 c[3] *= r_wateralpha.value;
10633 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10635 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10636 GL_DepthMask(false);
10638 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10640 GL_BlendFunc(GL_ONE, GL_ONE);
10641 GL_DepthMask(false);
10643 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10645 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10646 GL_DepthMask(false);
10648 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10650 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10651 GL_DepthMask(false);
10655 GL_BlendFunc(GL_ONE, GL_ZERO);
10656 GL_DepthMask(writedepth);
10659 rsurface.lightmapcolor4f = NULL;
10661 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10663 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10665 rsurface.lightmapcolor4f = NULL;
10666 rsurface.lightmapcolor4f_bufferobject = 0;
10667 rsurface.lightmapcolor4f_bufferoffset = 0;
10669 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10671 qboolean applycolor = true;
10674 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10676 r_refdef.lightmapintensity = 1;
10677 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10678 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10682 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10684 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10685 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10686 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10689 if(!rsurface.lightmapcolor4f)
10690 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10692 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10693 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10694 if(r_refdef.fogenabled)
10695 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10697 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10698 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10701 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10704 RSurf_SetupDepthAndCulling();
10705 if (r_showsurfaces.integer == 3 && !prepass)
10707 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10710 switch (vid.renderpath)
10712 case RENDERPATH_GL20:
10713 case RENDERPATH_CGGL:
10714 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10716 case RENDERPATH_GL13:
10717 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10719 case RENDERPATH_GL11:
10720 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10726 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10729 RSurf_SetupDepthAndCulling();
10730 if (r_showsurfaces.integer == 3 && !prepass)
10732 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10735 switch (vid.renderpath)
10737 case RENDERPATH_GL20:
10738 case RENDERPATH_CGGL:
10739 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10741 case RENDERPATH_GL13:
10742 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10744 case RENDERPATH_GL11:
10745 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10751 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10754 int texturenumsurfaces, endsurface;
10755 texture_t *texture;
10756 const msurface_t *surface;
10757 const msurface_t *texturesurfacelist[256];
10759 // if the model is static it doesn't matter what value we give for
10760 // wantnormals and wanttangents, so this logic uses only rules applicable
10761 // to a model, knowing that they are meaningless otherwise
10762 if (ent == r_refdef.scene.worldentity)
10763 RSurf_ActiveWorldEntity();
10764 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10765 RSurf_ActiveModelEntity(ent, false, false, false);
10768 switch (vid.renderpath)
10770 case RENDERPATH_GL20:
10771 case RENDERPATH_CGGL:
10772 RSurf_ActiveModelEntity(ent, true, true, false);
10774 case RENDERPATH_GL13:
10775 case RENDERPATH_GL11:
10776 RSurf_ActiveModelEntity(ent, true, false, false);
10781 if (r_transparentdepthmasking.integer)
10783 qboolean setup = false;
10784 for (i = 0;i < numsurfaces;i = j)
10787 surface = rsurface.modelsurfaces + surfacelist[i];
10788 texture = surface->texture;
10789 rsurface.texture = R_GetCurrentTexture(texture);
10790 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10791 // scan ahead until we find a different texture
10792 endsurface = min(i + 1024, numsurfaces);
10793 texturenumsurfaces = 0;
10794 texturesurfacelist[texturenumsurfaces++] = surface;
10795 for (;j < endsurface;j++)
10797 surface = rsurface.modelsurfaces + surfacelist[j];
10798 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10800 texturesurfacelist[texturenumsurfaces++] = surface;
10802 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10804 // render the range of surfaces as depth
10808 GL_ColorMask(0,0,0,0);
10810 GL_DepthTest(true);
10811 GL_BlendFunc(GL_ONE, GL_ZERO);
10812 GL_DepthMask(true);
10813 GL_AlphaTest(false);
10814 R_Mesh_ColorPointer(NULL, 0, 0);
10815 R_Mesh_ResetTextureState();
10816 R_SetupShader_DepthOrShadow();
10818 RSurf_SetupDepthAndCulling();
10819 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10820 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10823 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10826 for (i = 0;i < numsurfaces;i = j)
10829 surface = rsurface.modelsurfaces + surfacelist[i];
10830 texture = surface->texture;
10831 rsurface.texture = R_GetCurrentTexture(texture);
10832 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10833 // scan ahead until we find a different texture
10834 endsurface = min(i + 1024, numsurfaces);
10835 texturenumsurfaces = 0;
10836 texturesurfacelist[texturenumsurfaces++] = surface;
10837 for (;j < endsurface;j++)
10839 surface = rsurface.modelsurfaces + surfacelist[j];
10840 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10842 texturesurfacelist[texturenumsurfaces++] = surface;
10844 // render the range of surfaces
10845 if (ent == r_refdef.scene.worldentity)
10846 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10848 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10850 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10851 GL_AlphaTest(false);
10854 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10856 // transparent surfaces get pushed off into the transparent queue
10857 int surfacelistindex;
10858 const msurface_t *surface;
10859 vec3_t tempcenter, center;
10860 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10862 surface = texturesurfacelist[surfacelistindex];
10863 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10864 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10865 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10866 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10867 if (queueentity->transparent_offset) // transparent offset
10869 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10870 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10871 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10873 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10877 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10879 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10883 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10885 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10887 RSurf_SetupDepthAndCulling();
10888 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10889 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10893 if (!rsurface.texture->currentnumlayers)
10895 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10896 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10898 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10900 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10902 RSurf_SetupDepthAndCulling();
10903 GL_AlphaTest(false);
10904 R_Mesh_ColorPointer(NULL, 0, 0);
10905 R_Mesh_ResetTextureState();
10906 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10907 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10908 GL_DepthMask(true);
10909 GL_BlendFunc(GL_ONE, GL_ZERO);
10910 GL_Color(0, 0, 0, 1);
10911 GL_DepthTest(writedepth);
10912 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10914 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10916 RSurf_SetupDepthAndCulling();
10917 GL_AlphaTest(false);
10918 R_Mesh_ColorPointer(NULL, 0, 0);
10919 R_Mesh_ResetTextureState();
10920 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10921 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10922 GL_DepthMask(true);
10923 GL_BlendFunc(GL_ONE, GL_ZERO);
10924 GL_DepthTest(true);
10925 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10927 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10928 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10929 else if (!rsurface.texture->currentnumlayers)
10931 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10933 // in the deferred case, transparent surfaces were queued during prepass
10934 if (!r_shadow_usingdeferredprepass)
10935 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10939 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10940 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10945 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10948 texture_t *texture;
10949 // break the surface list down into batches by texture and use of lightmapping
10950 for (i = 0;i < numsurfaces;i = j)
10953 // texture is the base texture pointer, rsurface.texture is the
10954 // current frame/skin the texture is directing us to use (for example
10955 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10956 // use skin 1 instead)
10957 texture = surfacelist[i]->texture;
10958 rsurface.texture = R_GetCurrentTexture(texture);
10959 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10960 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10962 // if this texture is not the kind we want, skip ahead to the next one
10963 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10967 // simply scan ahead until we find a different texture or lightmap state
10968 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10970 // render the range of surfaces
10971 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10975 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10980 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10982 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10984 RSurf_SetupDepthAndCulling();
10985 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10986 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10990 if (!rsurface.texture->currentnumlayers)
10992 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10993 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10995 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10997 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10999 RSurf_SetupDepthAndCulling();
11000 GL_AlphaTest(false);
11001 R_Mesh_ColorPointer(NULL, 0, 0);
11002 R_Mesh_ResetTextureState();
11003 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11004 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11005 GL_DepthMask(true);
11006 GL_BlendFunc(GL_ONE, GL_ZERO);
11007 GL_Color(0, 0, 0, 1);
11008 GL_DepthTest(writedepth);
11009 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11011 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11013 RSurf_SetupDepthAndCulling();
11014 GL_AlphaTest(false);
11015 R_Mesh_ColorPointer(NULL, 0, 0);
11016 R_Mesh_ResetTextureState();
11017 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11018 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11019 GL_DepthMask(true);
11020 GL_BlendFunc(GL_ONE, GL_ZERO);
11021 GL_DepthTest(true);
11022 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11024 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11025 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11026 else if (!rsurface.texture->currentnumlayers)
11028 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11030 // in the deferred case, transparent surfaces were queued during prepass
11031 if (!r_shadow_usingdeferredprepass)
11032 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11036 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11037 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11042 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11045 texture_t *texture;
11046 // break the surface list down into batches by texture and use of lightmapping
11047 for (i = 0;i < numsurfaces;i = j)
11050 // texture is the base texture pointer, rsurface.texture is the
11051 // current frame/skin the texture is directing us to use (for example
11052 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11053 // use skin 1 instead)
11054 texture = surfacelist[i]->texture;
11055 rsurface.texture = R_GetCurrentTexture(texture);
11056 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11057 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11059 // if this texture is not the kind we want, skip ahead to the next one
11060 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11064 // simply scan ahead until we find a different texture or lightmap state
11065 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11067 // render the range of surfaces
11068 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11072 float locboxvertex3f[6*4*3] =
11074 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11075 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11076 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11077 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11078 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11079 1,0,0, 0,0,0, 0,1,0, 1,1,0
11082 unsigned short locboxelements[6*2*3] =
11087 12,13,14, 12,14,15,
11088 16,17,18, 16,18,19,
11092 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11095 cl_locnode_t *loc = (cl_locnode_t *)ent;
11097 float vertex3f[6*4*3];
11099 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11100 GL_DepthMask(false);
11101 GL_DepthRange(0, 1);
11102 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11103 GL_DepthTest(true);
11104 GL_CullFace(GL_NONE);
11105 R_EntityMatrix(&identitymatrix);
11107 R_Mesh_VertexPointer(vertex3f, 0, 0);
11108 R_Mesh_ColorPointer(NULL, 0, 0);
11109 R_Mesh_ResetTextureState();
11110 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11112 i = surfacelist[0];
11113 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11114 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11115 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11116 surfacelist[0] < 0 ? 0.5f : 0.125f);
11118 if (VectorCompare(loc->mins, loc->maxs))
11120 VectorSet(size, 2, 2, 2);
11121 VectorMA(loc->mins, -0.5f, size, mins);
11125 VectorCopy(loc->mins, mins);
11126 VectorSubtract(loc->maxs, loc->mins, size);
11129 for (i = 0;i < 6*4*3;)
11130 for (j = 0;j < 3;j++, i++)
11131 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11133 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11136 void R_DrawLocs(void)
11139 cl_locnode_t *loc, *nearestloc;
11141 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11142 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11144 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11145 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11149 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11151 if (decalsystem->decals)
11152 Mem_Free(decalsystem->decals);
11153 memset(decalsystem, 0, sizeof(*decalsystem));
11156 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)
11159 tridecal_t *decals;
11163 // expand or initialize the system
11164 if (decalsystem->maxdecals <= decalsystem->numdecals)
11166 decalsystem_t old = *decalsystem;
11167 qboolean useshortelements;
11168 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11169 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11170 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)));
11171 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11172 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11173 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11174 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11175 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11176 if (decalsystem->numdecals)
11177 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11179 Mem_Free(old.decals);
11180 for (i = 0;i < decalsystem->maxdecals*3;i++)
11181 decalsystem->element3i[i] = i;
11182 if (useshortelements)
11183 for (i = 0;i < decalsystem->maxdecals*3;i++)
11184 decalsystem->element3s[i] = i;
11187 // grab a decal and search for another free slot for the next one
11188 maxdecals = decalsystem->maxdecals;
11189 decals = decalsystem->decals;
11190 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11191 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11193 decalsystem->freedecal = i;
11194 if (decalsystem->numdecals <= i)
11195 decalsystem->numdecals = i + 1;
11197 // initialize the decal
11199 decal->triangleindex = triangleindex;
11200 decal->surfaceindex = surfaceindex;
11201 decal->decalsequence = decalsequence;
11202 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11203 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11204 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11205 decal->color4ub[0][3] = 255;
11206 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11207 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11208 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11209 decal->color4ub[1][3] = 255;
11210 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11211 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11212 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11213 decal->color4ub[2][3] = 255;
11214 decal->vertex3f[0][0] = v0[0];
11215 decal->vertex3f[0][1] = v0[1];
11216 decal->vertex3f[0][2] = v0[2];
11217 decal->vertex3f[1][0] = v1[0];
11218 decal->vertex3f[1][1] = v1[1];
11219 decal->vertex3f[1][2] = v1[2];
11220 decal->vertex3f[2][0] = v2[0];
11221 decal->vertex3f[2][1] = v2[1];
11222 decal->vertex3f[2][2] = v2[2];
11223 decal->texcoord2f[0][0] = t0[0];
11224 decal->texcoord2f[0][1] = t0[1];
11225 decal->texcoord2f[1][0] = t1[0];
11226 decal->texcoord2f[1][1] = t1[1];
11227 decal->texcoord2f[2][0] = t2[0];
11228 decal->texcoord2f[2][1] = t2[1];
11231 extern cvar_t cl_decals_bias;
11232 extern cvar_t cl_decals_models;
11233 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11234 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)
11236 matrix4x4_t projection;
11237 decalsystem_t *decalsystem;
11240 const float *vertex3f;
11241 const msurface_t *surface;
11242 const msurface_t *surfaces;
11243 const int *surfacelist;
11244 const texture_t *texture;
11247 int numsurfacelist;
11248 int surfacelistindex;
11251 int decalsurfaceindex;
11256 float localorigin[3];
11257 float localnormal[3];
11258 float localmins[3];
11259 float localmaxs[3];
11266 float planes[6][4];
11268 float points[2][9][3];
11272 decalsystem = &ent->decalsystem;
11273 model = ent->model;
11274 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11276 R_DecalSystem_Reset(&ent->decalsystem);
11280 if (!model->brush.data_nodes && !cl_decals_models.integer)
11282 if (decalsystem->model)
11283 R_DecalSystem_Reset(decalsystem);
11287 if (decalsystem->model != model)
11288 R_DecalSystem_Reset(decalsystem);
11289 decalsystem->model = model;
11291 RSurf_ActiveModelEntity(ent, false, false, false);
11293 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11294 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11295 VectorNormalize(localnormal);
11296 localsize = worldsize*rsurface.inversematrixscale;
11297 ilocalsize = 1.0f / localsize;
11298 localmins[0] = localorigin[0] - localsize;
11299 localmins[1] = localorigin[1] - localsize;
11300 localmins[2] = localorigin[2] - localsize;
11301 localmaxs[0] = localorigin[0] + localsize;
11302 localmaxs[1] = localorigin[1] + localsize;
11303 localmaxs[2] = localorigin[2] + localsize;
11305 //VectorCopy(localnormal, planes[4]);
11306 //VectorVectors(planes[4], planes[2], planes[0]);
11307 AnglesFromVectors(angles, localnormal, NULL, false);
11308 AngleVectors(angles, planes[0], planes[2], planes[4]);
11309 VectorNegate(planes[0], planes[1]);
11310 VectorNegate(planes[2], planes[3]);
11311 VectorNegate(planes[4], planes[5]);
11312 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11313 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11314 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11315 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11316 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11317 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11322 matrix4x4_t forwardprojection;
11323 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11324 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11329 float projectionvector[4][3];
11330 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11331 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11332 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11333 projectionvector[0][0] = planes[0][0] * ilocalsize;
11334 projectionvector[0][1] = planes[1][0] * ilocalsize;
11335 projectionvector[0][2] = planes[2][0] * ilocalsize;
11336 projectionvector[1][0] = planes[0][1] * ilocalsize;
11337 projectionvector[1][1] = planes[1][1] * ilocalsize;
11338 projectionvector[1][2] = planes[2][1] * ilocalsize;
11339 projectionvector[2][0] = planes[0][2] * ilocalsize;
11340 projectionvector[2][1] = planes[1][2] * ilocalsize;
11341 projectionvector[2][2] = planes[2][2] * ilocalsize;
11342 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11343 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11344 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11345 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11349 dynamic = model->surfmesh.isanimated;
11350 vertex3f = rsurface.modelvertex3f;
11351 numsurfacelist = model->nummodelsurfaces;
11352 surfacelist = model->sortedmodelsurfaces;
11353 surfaces = model->data_surfaces;
11354 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11356 surfaceindex = surfacelist[surfacelistindex];
11357 surface = surfaces + surfaceindex;
11358 // skip transparent surfaces
11359 texture = surface->texture;
11360 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11362 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11364 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11366 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11367 numvertices = surface->num_vertices;
11368 numtriangles = surface->num_triangles;
11369 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11371 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11373 index = 3*e[cornerindex];
11374 VectorCopy(vertex3f + index, v[cornerindex]);
11377 //TriangleNormal(v[0], v[1], v[2], normal);
11378 //if (DotProduct(normal, localnormal) < 0.0f)
11380 // clip by each of the box planes formed from the projection matrix
11381 // if anything survives, we emit the decal
11382 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]);
11385 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]);
11388 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]);
11391 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]);
11394 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]);
11397 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]);
11400 // some part of the triangle survived, so we have to accept it...
11403 // dynamic always uses the original triangle
11405 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11407 index = 3*e[cornerindex];
11408 VectorCopy(vertex3f + index, v[cornerindex]);
11411 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11413 // convert vertex positions to texcoords
11414 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11415 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11416 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11417 // calculate distance fade from the projection origin
11418 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11419 f = bound(0.0f, f, 1.0f);
11420 c[cornerindex][0] = r * f;
11421 c[cornerindex][1] = g * f;
11422 c[cornerindex][2] = b * f;
11423 c[cornerindex][3] = 1.0f;
11424 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11427 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);
11429 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11430 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);
11435 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11436 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)
11438 int renderentityindex;
11439 float worldmins[3];
11440 float worldmaxs[3];
11441 entity_render_t *ent;
11443 if (!cl_decals_newsystem.integer)
11446 worldmins[0] = worldorigin[0] - worldsize;
11447 worldmins[1] = worldorigin[1] - worldsize;
11448 worldmins[2] = worldorigin[2] - worldsize;
11449 worldmaxs[0] = worldorigin[0] + worldsize;
11450 worldmaxs[1] = worldorigin[1] + worldsize;
11451 worldmaxs[2] = worldorigin[2] + worldsize;
11453 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11455 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11457 ent = r_refdef.scene.entities[renderentityindex];
11458 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11461 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11465 typedef struct r_decalsystem_splatqueue_s
11467 vec3_t worldorigin;
11468 vec3_t worldnormal;
11474 r_decalsystem_splatqueue_t;
11476 int r_decalsystem_numqueued = 0;
11477 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11479 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)
11481 r_decalsystem_splatqueue_t *queue;
11483 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11486 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11487 VectorCopy(worldorigin, queue->worldorigin);
11488 VectorCopy(worldnormal, queue->worldnormal);
11489 Vector4Set(queue->color, r, g, b, a);
11490 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11491 queue->worldsize = worldsize;
11492 queue->decalsequence = cl.decalsequence++;
11495 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11498 r_decalsystem_splatqueue_t *queue;
11500 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11501 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);
11502 r_decalsystem_numqueued = 0;
11505 extern cvar_t cl_decals_max;
11506 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11509 decalsystem_t *decalsystem = &ent->decalsystem;
11516 if (!decalsystem->numdecals)
11519 if (r_showsurfaces.integer)
11522 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11524 R_DecalSystem_Reset(decalsystem);
11528 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11529 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11531 if (decalsystem->lastupdatetime)
11532 frametime = (cl.time - decalsystem->lastupdatetime);
11535 decalsystem->lastupdatetime = cl.time;
11536 decal = decalsystem->decals;
11537 numdecals = decalsystem->numdecals;
11539 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11541 if (decal->color4ub[0][3])
11543 decal->lived += frametime;
11544 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11546 memset(decal, 0, sizeof(*decal));
11547 if (decalsystem->freedecal > i)
11548 decalsystem->freedecal = i;
11552 decal = decalsystem->decals;
11553 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11556 // collapse the array by shuffling the tail decals into the gaps
11559 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11560 decalsystem->freedecal++;
11561 if (decalsystem->freedecal == numdecals)
11563 decal[decalsystem->freedecal] = decal[--numdecals];
11566 decalsystem->numdecals = numdecals;
11568 if (numdecals <= 0)
11570 // if there are no decals left, reset decalsystem
11571 R_DecalSystem_Reset(decalsystem);
11575 extern skinframe_t *decalskinframe;
11576 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11579 decalsystem_t *decalsystem = &ent->decalsystem;
11589 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11592 numdecals = decalsystem->numdecals;
11596 if (r_showsurfaces.integer)
11599 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11601 R_DecalSystem_Reset(decalsystem);
11605 // if the model is static it doesn't matter what value we give for
11606 // wantnormals and wanttangents, so this logic uses only rules applicable
11607 // to a model, knowing that they are meaningless otherwise
11608 if (ent == r_refdef.scene.worldentity)
11609 RSurf_ActiveWorldEntity();
11611 RSurf_ActiveModelEntity(ent, false, false, false);
11613 decalsystem->lastupdatetime = cl.time;
11614 decal = decalsystem->decals;
11616 fadedelay = cl_decals_time.value;
11617 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11619 // update vertex positions for animated models
11620 v3f = decalsystem->vertex3f;
11621 c4f = decalsystem->color4f;
11622 t2f = decalsystem->texcoord2f;
11623 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11625 if (!decal->color4ub[0][3])
11628 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11631 // update color values for fading decals
11632 if (decal->lived >= cl_decals_time.value)
11634 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11635 alpha *= (1.0f/255.0f);
11638 alpha = 1.0f/255.0f;
11640 c4f[ 0] = decal->color4ub[0][0] * alpha;
11641 c4f[ 1] = decal->color4ub[0][1] * alpha;
11642 c4f[ 2] = decal->color4ub[0][2] * alpha;
11644 c4f[ 4] = decal->color4ub[1][0] * alpha;
11645 c4f[ 5] = decal->color4ub[1][1] * alpha;
11646 c4f[ 6] = decal->color4ub[1][2] * alpha;
11648 c4f[ 8] = decal->color4ub[2][0] * alpha;
11649 c4f[ 9] = decal->color4ub[2][1] * alpha;
11650 c4f[10] = decal->color4ub[2][2] * alpha;
11653 t2f[0] = decal->texcoord2f[0][0];
11654 t2f[1] = decal->texcoord2f[0][1];
11655 t2f[2] = decal->texcoord2f[1][0];
11656 t2f[3] = decal->texcoord2f[1][1];
11657 t2f[4] = decal->texcoord2f[2][0];
11658 t2f[5] = decal->texcoord2f[2][1];
11660 // update vertex positions for animated models
11661 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11663 e = rsurface.modelelement3i + 3*decal->triangleindex;
11664 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11665 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11666 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11670 VectorCopy(decal->vertex3f[0], v3f);
11671 VectorCopy(decal->vertex3f[1], v3f + 3);
11672 VectorCopy(decal->vertex3f[2], v3f + 6);
11683 r_refdef.stats.drawndecals += numtris;
11685 if (r_refdef.fogenabled)
11687 switch(vid.renderpath)
11689 case RENDERPATH_GL20:
11690 case RENDERPATH_CGGL:
11691 case RENDERPATH_GL13:
11692 case RENDERPATH_GL11:
11693 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11695 alpha = RSurf_FogVertex(v3f);
11704 // now render the decals all at once
11705 // (this assumes they all use one particle font texture!)
11706 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);
11707 R_Mesh_ResetTextureState();
11708 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11709 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11710 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11711 GL_DepthMask(false);
11712 GL_DepthRange(0, 1);
11713 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11714 GL_DepthTest(true);
11715 GL_CullFace(GL_NONE);
11716 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11717 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11718 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11722 static void R_DrawModelDecals(void)
11726 // fade faster when there are too many decals
11727 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11728 for (i = 0;i < r_refdef.scene.numentities;i++)
11729 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11731 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11732 for (i = 0;i < r_refdef.scene.numentities;i++)
11733 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11734 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11736 R_DecalSystem_ApplySplatEntitiesQueue();
11738 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11739 for (i = 0;i < r_refdef.scene.numentities;i++)
11740 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11742 r_refdef.stats.totaldecals += numdecals;
11744 if (r_showsurfaces.integer)
11747 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11749 for (i = 0;i < r_refdef.scene.numentities;i++)
11751 if (!r_refdef.viewcache.entityvisible[i])
11753 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11754 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11758 void R_DrawDebugModel(void)
11760 entity_render_t *ent = rsurface.entity;
11761 int i, j, k, l, flagsmask;
11762 const int *elements;
11764 const msurface_t *surface;
11765 dp_model_t *model = ent->model;
11768 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11770 R_Mesh_ColorPointer(NULL, 0, 0);
11771 R_Mesh_ResetTextureState();
11772 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11773 GL_DepthRange(0, 1);
11774 GL_DepthTest(!r_showdisabledepthtest.integer);
11775 GL_DepthMask(false);
11776 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11778 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11780 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11781 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11783 if (brush->colbrushf && brush->colbrushf->numtriangles)
11785 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11786 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);
11787 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11790 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11792 if (surface->num_collisiontriangles)
11794 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11795 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);
11796 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11801 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11803 if (r_showtris.integer || r_shownormals.integer)
11805 if (r_showdisabledepthtest.integer)
11807 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11808 GL_DepthMask(false);
11812 GL_BlendFunc(GL_ONE, GL_ZERO);
11813 GL_DepthMask(true);
11815 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11817 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11819 rsurface.texture = R_GetCurrentTexture(surface->texture);
11820 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11822 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11823 if (r_showtris.value > 0)
11825 if (!rsurface.texture->currentlayers->depthmask)
11826 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11827 else if (ent == r_refdef.scene.worldentity)
11828 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11830 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11831 elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11832 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11833 R_Mesh_ColorPointer(NULL, 0, 0);
11834 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11835 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11836 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11837 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);
11838 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11841 if (r_shownormals.value < 0)
11843 qglBegin(GL_LINES);
11844 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11846 VectorCopy(rsurface.vertex3f + l * 3, v);
11847 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11848 qglVertex3f(v[0], v[1], v[2]);
11849 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11850 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11851 qglVertex3f(v[0], v[1], v[2]);
11856 if (r_shownormals.value > 0)
11858 qglBegin(GL_LINES);
11859 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11861 VectorCopy(rsurface.vertex3f + l * 3, v);
11862 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11863 qglVertex3f(v[0], v[1], v[2]);
11864 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11865 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11866 qglVertex3f(v[0], v[1], v[2]);
11870 qglBegin(GL_LINES);
11871 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11873 VectorCopy(rsurface.vertex3f + l * 3, v);
11874 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11875 qglVertex3f(v[0], v[1], v[2]);
11876 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11877 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11878 qglVertex3f(v[0], v[1], v[2]);
11882 qglBegin(GL_LINES);
11883 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11885 VectorCopy(rsurface.vertex3f + l * 3, v);
11886 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11887 qglVertex3f(v[0], v[1], v[2]);
11888 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11889 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11890 qglVertex3f(v[0], v[1], v[2]);
11897 rsurface.texture = NULL;
11901 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11902 int r_maxsurfacelist = 0;
11903 const msurface_t **r_surfacelist = NULL;
11904 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11906 int i, j, endj, f, flagsmask;
11908 dp_model_t *model = r_refdef.scene.worldmodel;
11909 msurface_t *surfaces;
11910 unsigned char *update;
11911 int numsurfacelist = 0;
11915 if (r_maxsurfacelist < model->num_surfaces)
11917 r_maxsurfacelist = model->num_surfaces;
11919 Mem_Free((msurface_t**)r_surfacelist);
11920 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11923 RSurf_ActiveWorldEntity();
11925 surfaces = model->data_surfaces;
11926 update = model->brushq1.lightmapupdateflags;
11928 // update light styles on this submodel
11929 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11931 model_brush_lightstyleinfo_t *style;
11932 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11934 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11936 int *list = style->surfacelist;
11937 style->value = r_refdef.scene.lightstylevalue[style->style];
11938 for (j = 0;j < style->numsurfaces;j++)
11939 update[list[j]] = true;
11944 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11948 R_DrawDebugModel();
11949 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11955 rsurface.uselightmaptexture = false;
11956 rsurface.texture = NULL;
11957 rsurface.rtlight = NULL;
11958 numsurfacelist = 0;
11959 // add visible surfaces to draw list
11960 for (i = 0;i < model->nummodelsurfaces;i++)
11962 j = model->sortedmodelsurfaces[i];
11963 if (r_refdef.viewcache.world_surfacevisible[j])
11964 r_surfacelist[numsurfacelist++] = surfaces + j;
11966 // update lightmaps if needed
11967 if (model->brushq1.firstrender)
11969 model->brushq1.firstrender = false;
11970 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11972 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11976 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11977 if (r_refdef.viewcache.world_surfacevisible[j])
11979 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11981 // don't do anything if there were no surfaces
11982 if (!numsurfacelist)
11984 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11987 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11988 GL_AlphaTest(false);
11990 // add to stats if desired
11991 if (r_speeds.integer && !skysurfaces && !depthonly)
11993 r_refdef.stats.world_surfaces += numsurfacelist;
11994 for (j = 0;j < numsurfacelist;j++)
11995 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11998 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12001 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12003 int i, j, endj, f, flagsmask;
12005 dp_model_t *model = ent->model;
12006 msurface_t *surfaces;
12007 unsigned char *update;
12008 int numsurfacelist = 0;
12012 if (r_maxsurfacelist < model->num_surfaces)
12014 r_maxsurfacelist = model->num_surfaces;
12016 Mem_Free((msurface_t **)r_surfacelist);
12017 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12020 // if the model is static it doesn't matter what value we give for
12021 // wantnormals and wanttangents, so this logic uses only rules applicable
12022 // to a model, knowing that they are meaningless otherwise
12023 if (ent == r_refdef.scene.worldentity)
12024 RSurf_ActiveWorldEntity();
12025 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12026 RSurf_ActiveModelEntity(ent, false, false, false);
12028 RSurf_ActiveModelEntity(ent, true, true, true);
12029 else if (depthonly)
12030 RSurf_ActiveModelEntity(ent, false, false, false);
12033 switch (vid.renderpath)
12035 case RENDERPATH_GL20:
12036 case RENDERPATH_CGGL:
12037 RSurf_ActiveModelEntity(ent, true, true, false);
12039 case RENDERPATH_GL13:
12040 case RENDERPATH_GL11:
12041 RSurf_ActiveModelEntity(ent, true, false, false);
12046 surfaces = model->data_surfaces;
12047 update = model->brushq1.lightmapupdateflags;
12049 // update light styles
12050 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12052 model_brush_lightstyleinfo_t *style;
12053 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12055 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12057 int *list = style->surfacelist;
12058 style->value = r_refdef.scene.lightstylevalue[style->style];
12059 for (j = 0;j < style->numsurfaces;j++)
12060 update[list[j]] = true;
12065 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12069 R_DrawDebugModel();
12070 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12076 rsurface.uselightmaptexture = false;
12077 rsurface.texture = NULL;
12078 rsurface.rtlight = NULL;
12079 numsurfacelist = 0;
12080 // add visible surfaces to draw list
12081 for (i = 0;i < model->nummodelsurfaces;i++)
12082 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12083 // don't do anything if there were no surfaces
12084 if (!numsurfacelist)
12086 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12089 // update lightmaps if needed
12093 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12098 R_BuildLightMap(ent, surfaces + j);
12103 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12105 R_BuildLightMap(ent, surfaces + j);
12106 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12107 GL_AlphaTest(false);
12109 // add to stats if desired
12110 if (r_speeds.integer && !skysurfaces && !depthonly)
12112 r_refdef.stats.entities_surfaces += numsurfacelist;
12113 for (j = 0;j < numsurfacelist;j++)
12114 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12117 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12120 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12122 static texture_t texture;
12123 static msurface_t surface;
12124 const msurface_t *surfacelist = &surface;
12126 // fake enough texture and surface state to render this geometry
12128 texture.update_lastrenderframe = -1; // regenerate this texture
12129 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12130 texture.currentskinframe = skinframe;
12131 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12132 texture.specularscalemod = 1;
12133 texture.specularpowermod = 1;
12135 surface.texture = &texture;
12136 surface.num_triangles = numtriangles;
12137 surface.num_firsttriangle = firsttriangle;
12138 surface.num_vertices = numvertices;
12139 surface.num_firstvertex = firstvertex;
12142 rsurface.texture = R_GetCurrentTexture(surface.texture);
12143 rsurface.uselightmaptexture = false;
12144 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12147 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)
12149 static msurface_t surface;
12150 const msurface_t *surfacelist = &surface;
12152 // fake enough texture and surface state to render this geometry
12154 surface.texture = texture;
12155 surface.num_triangles = numtriangles;
12156 surface.num_firsttriangle = firsttriangle;
12157 surface.num_vertices = numvertices;
12158 surface.num_firstvertex = firstvertex;
12161 rsurface.texture = R_GetCurrentTexture(surface.texture);
12162 rsurface.uselightmaptexture = false;
12163 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);