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_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
116 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
117 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
118 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
119 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
121 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
122 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
123 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
125 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)"};
126 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
127 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
128 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
129 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
130 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)"};
131 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)"};
132 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)"};
133 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)"};
135 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)"};
136 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
137 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"};
138 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
139 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
141 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
142 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
143 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
144 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
146 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
147 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
148 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
149 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
150 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
151 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
152 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
154 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
155 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
156 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
157 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)"};
159 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"};
161 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"};
163 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
165 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
166 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
167 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"};
168 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
169 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
170 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
171 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
172 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)"};
174 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
176 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)"};
178 extern cvar_t v_glslgamma;
180 extern qboolean v_flipped_state;
182 static struct r_bloomstate_s
187 int bloomwidth, bloomheight;
189 int screentexturewidth, screentextureheight;
190 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
192 int bloomtexturewidth, bloomtextureheight;
193 rtexture_t *texture_bloom;
195 // arrays for rendering the screen passes
196 float screentexcoord2f[8];
197 float bloomtexcoord2f[8];
198 float offsettexcoord2f[8];
200 r_viewport_t viewport;
204 r_waterstate_t r_waterstate;
206 /// shadow volume bsp struct with automatically growing nodes buffer
209 rtexture_t *r_texture_blanknormalmap;
210 rtexture_t *r_texture_white;
211 rtexture_t *r_texture_grey128;
212 rtexture_t *r_texture_black;
213 rtexture_t *r_texture_notexture;
214 rtexture_t *r_texture_whitecube;
215 rtexture_t *r_texture_normalizationcube;
216 rtexture_t *r_texture_fogattenuation;
217 rtexture_t *r_texture_gammaramps;
218 unsigned int r_texture_gammaramps_serial;
219 //rtexture_t *r_texture_fogintensity;
220 rtexture_t *r_texture_reflectcube;
222 // TODO: hash lookups?
223 typedef struct cubemapinfo_s
230 int r_texture_numcubemaps;
231 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
233 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
234 unsigned int r_numqueries;
235 unsigned int r_maxqueries;
237 typedef struct r_qwskincache_s
239 char name[MAX_QPATH];
240 skinframe_t *skinframe;
244 static r_qwskincache_t *r_qwskincache;
245 static int r_qwskincache_size;
247 /// vertex coordinates for a quad that covers the screen exactly
248 const float r_screenvertex3f[12] =
256 extern void R_DrawModelShadows(void);
258 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
261 for (i = 0;i < verts;i++)
272 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
275 for (i = 0;i < verts;i++)
285 // FIXME: move this to client?
288 if (gamemode == GAME_NEHAHRA)
290 Cvar_Set("gl_fogenable", "0");
291 Cvar_Set("gl_fogdensity", "0.2");
292 Cvar_Set("gl_fogred", "0.3");
293 Cvar_Set("gl_foggreen", "0.3");
294 Cvar_Set("gl_fogblue", "0.3");
296 r_refdef.fog_density = 0;
297 r_refdef.fog_red = 0;
298 r_refdef.fog_green = 0;
299 r_refdef.fog_blue = 0;
300 r_refdef.fog_alpha = 1;
301 r_refdef.fog_start = 0;
302 r_refdef.fog_end = 16384;
303 r_refdef.fog_height = 1<<30;
304 r_refdef.fog_fadedepth = 128;
307 static void R_BuildBlankTextures(void)
309 unsigned char data[4];
310 data[2] = 128; // normal X
311 data[1] = 128; // normal Y
312 data[0] = 255; // normal Z
313 data[3] = 128; // height
314 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
319 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
324 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
329 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
332 static void R_BuildNoTexture(void)
335 unsigned char pix[16][16][4];
336 // this makes a light grey/dark grey checkerboard texture
337 for (y = 0;y < 16;y++)
339 for (x = 0;x < 16;x++)
341 if ((y < 8) ^ (x < 8))
357 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
360 static void R_BuildWhiteCube(void)
362 unsigned char data[6*1*1*4];
363 memset(data, 255, sizeof(data));
364 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
367 static void R_BuildNormalizationCube(void)
371 vec_t s, t, intensity;
374 data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
375 for (side = 0;side < 6;side++)
377 for (y = 0;y < NORMSIZE;y++)
379 for (x = 0;x < NORMSIZE;x++)
381 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
382 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
417 intensity = 127.0f / sqrt(DotProduct(v, v));
418 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
419 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
420 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
421 data[((side*64+y)*64+x)*4+3] = 255;
425 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
429 static void R_BuildFogTexture(void)
433 unsigned char data1[FOGWIDTH][4];
434 //unsigned char data2[FOGWIDTH][4];
437 r_refdef.fogmasktable_start = r_refdef.fog_start;
438 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
439 r_refdef.fogmasktable_range = r_refdef.fogrange;
440 r_refdef.fogmasktable_density = r_refdef.fog_density;
442 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
443 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
445 d = (x * r - r_refdef.fogmasktable_start);
446 if(developer_extra.integer)
447 Con_DPrintf("%f ", d);
449 if (r_fog_exp2.integer)
450 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
452 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
453 if(developer_extra.integer)
454 Con_DPrintf(" : %f ", alpha);
455 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
456 if(developer_extra.integer)
457 Con_DPrintf(" = %f\n", alpha);
458 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
461 for (x = 0;x < FOGWIDTH;x++)
463 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
468 //data2[x][0] = 255 - b;
469 //data2[x][1] = 255 - b;
470 //data2[x][2] = 255 - b;
473 if (r_texture_fogattenuation)
475 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
476 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
480 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);
481 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
485 //=======================================================================================================================================================
487 static const char *builtinshaderstring =
488 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
489 "// written by Forest 'LordHavoc' Hale\n"
490 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
492 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
495 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
496 "#define USELIGHTMAP\n"
498 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
499 "#define USEEYEVECTOR\n"
502 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
503 "# extension GL_ARB_texture_rectangle : enable\n"
506 "#ifdef USESHADOWMAP2D\n"
507 "# ifdef GL_EXT_gpu_shader4\n"
508 "# extension GL_EXT_gpu_shader4 : enable\n"
510 "# ifdef GL_ARB_texture_gather\n"
511 "# extension GL_ARB_texture_gather : enable\n"
513 "# ifdef GL_AMD_texture_texture4\n"
514 "# extension GL_AMD_texture_texture4 : enable\n"
519 "#ifdef USESHADOWMAPCUBE\n"
520 "# extension GL_EXT_gpu_shader4 : enable\n"
523 "//#ifdef USESHADOWSAMPLER\n"
524 "//# extension GL_ARB_shadow : enable\n"
527 "//#ifdef __GLSL_CG_DATA_TYPES\n"
528 "//# define myhalf half\n"
529 "//# define myhalf2 half2\n"
530 "//# define myhalf3 half3\n"
531 "//# define myhalf4 half4\n"
533 "# define myhalf float\n"
534 "# define myhalf2 vec2\n"
535 "# define myhalf3 vec3\n"
536 "# define myhalf4 vec4\n"
539 "#ifdef VERTEX_SHADER\n"
540 "uniform mat4 ModelViewProjectionMatrix;\n"
543 "#ifdef MODE_DEPTH_OR_SHADOW\n"
544 "#ifdef VERTEX_SHADER\n"
547 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
550 "#else // !MODE_DEPTH_ORSHADOW\n"
555 "#ifdef MODE_SHOWDEPTH\n"
556 "#ifdef VERTEX_SHADER\n"
559 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
560 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
564 "#ifdef FRAGMENT_SHADER\n"
567 " gl_FragColor = gl_Color;\n"
570 "#else // !MODE_SHOWDEPTH\n"
575 "#ifdef MODE_POSTPROCESS\n"
576 "varying vec2 TexCoord1;\n"
577 "varying vec2 TexCoord2;\n"
579 "#ifdef VERTEX_SHADER\n"
582 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
583 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
585 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
590 "#ifdef FRAGMENT_SHADER\n"
591 "uniform sampler2D Texture_First;\n"
593 "uniform sampler2D Texture_Second;\n"
595 "#ifdef USEGAMMARAMPS\n"
596 "uniform sampler2D Texture_GammaRamps;\n"
598 "#ifdef USESATURATION\n"
599 "uniform float Saturation;\n"
601 "#ifdef USEVIEWTINT\n"
602 "uniform vec4 ViewTintColor;\n"
604 "//uncomment these if you want to use them:\n"
605 "uniform vec4 UserVec1;\n"
606 "// uniform vec4 UserVec2;\n"
607 "// uniform vec4 UserVec3;\n"
608 "// uniform vec4 UserVec4;\n"
609 "// uniform float ClientTime;\n"
610 "uniform vec2 PixelSize;\n"
613 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
615 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
617 "#ifdef USEVIEWTINT\n"
618 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
621 "#ifdef USEPOSTPROCESSING\n"
622 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
623 "// 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"
624 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
625 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
626 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
627 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
628 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
629 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
632 "#ifdef USESATURATION\n"
633 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
634 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
635 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
636 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
639 "#ifdef USEGAMMARAMPS\n"
640 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
641 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
642 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
646 "#else // !MODE_POSTPROCESS\n"
651 "#ifdef MODE_GENERIC\n"
652 "#ifdef USEDIFFUSE\n"
653 "varying vec2 TexCoord1;\n"
655 "#ifdef USESPECULAR\n"
656 "varying vec2 TexCoord2;\n"
658 "#ifdef VERTEX_SHADER\n"
661 " gl_FrontColor = gl_Color;\n"
662 "#ifdef USEDIFFUSE\n"
663 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
665 "#ifdef USESPECULAR\n"
666 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
668 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
672 "#ifdef FRAGMENT_SHADER\n"
673 "#ifdef USEDIFFUSE\n"
674 "uniform sampler2D Texture_First;\n"
676 "#ifdef USESPECULAR\n"
677 "uniform sampler2D Texture_Second;\n"
682 " gl_FragColor = gl_Color;\n"
683 "#ifdef USEDIFFUSE\n"
684 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
687 "#ifdef USESPECULAR\n"
688 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
689 "# ifdef USECOLORMAPPING\n"
690 " gl_FragColor *= tex2;\n"
693 " gl_FragColor += tex2;\n"
695 "# ifdef USEVERTEXTEXTUREBLEND\n"
696 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
701 "#else // !MODE_GENERIC\n"
706 "#ifdef MODE_BLOOMBLUR\n"
707 "varying TexCoord;\n"
708 "#ifdef VERTEX_SHADER\n"
711 " gl_FrontColor = gl_Color;\n"
712 " TexCoord = gl_MultiTexCoord0.xy;\n"
713 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
717 "#ifdef FRAGMENT_SHADER\n"
718 "uniform sampler2D Texture_First;\n"
719 "uniform vec4 BloomBlur_Parameters;\n"
724 " vec2 tc = TexCoord;\n"
725 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
726 " tc += BloomBlur_Parameters.xy;\n"
727 " for (i = 1;i < SAMPLES;i++)\n"
729 " color += texture2D(Texture_First, tc).rgb;\n"
730 " tc += BloomBlur_Parameters.xy;\n"
732 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
735 "#else // !MODE_BLOOMBLUR\n"
736 "#ifdef MODE_REFRACTION\n"
737 "varying vec2 TexCoord;\n"
738 "varying vec4 ModelViewProjectionPosition;\n"
739 "uniform mat4 TexMatrix;\n"
740 "#ifdef VERTEX_SHADER\n"
744 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
745 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
746 " ModelViewProjectionPosition = gl_Position;\n"
750 "#ifdef FRAGMENT_SHADER\n"
751 "uniform sampler2D Texture_Normal;\n"
752 "uniform sampler2D Texture_Refraction;\n"
753 "uniform sampler2D Texture_Reflection;\n"
755 "uniform vec4 DistortScaleRefractReflect;\n"
756 "uniform vec4 ScreenScaleRefractReflect;\n"
757 "uniform vec4 ScreenCenterRefractReflect;\n"
758 "uniform vec4 RefractColor;\n"
759 "uniform vec4 ReflectColor;\n"
760 "uniform float ReflectFactor;\n"
761 "uniform float ReflectOffset;\n"
765 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
766 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
767 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
768 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
769 " // FIXME temporary hack to detect the case that the reflection\n"
770 " // gets blackened at edges due to leaving the area that contains actual\n"
772 " // Remove this 'ack once we have a better way to stop this thing from\n"
774 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
775 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
776 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
777 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
778 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
779 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
782 "#else // !MODE_REFRACTION\n"
787 "#ifdef MODE_WATER\n"
788 "varying vec2 TexCoord;\n"
789 "varying vec3 EyeVector;\n"
790 "varying vec4 ModelViewProjectionPosition;\n"
791 "#ifdef VERTEX_SHADER\n"
792 "uniform vec3 EyePosition;\n"
793 "uniform mat4 TexMatrix;\n"
797 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
798 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
799 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
800 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
801 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
802 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
803 " ModelViewProjectionPosition = gl_Position;\n"
807 "#ifdef FRAGMENT_SHADER\n"
808 "uniform sampler2D Texture_Normal;\n"
809 "uniform sampler2D Texture_Refraction;\n"
810 "uniform sampler2D Texture_Reflection;\n"
812 "uniform vec4 DistortScaleRefractReflect;\n"
813 "uniform vec4 ScreenScaleRefractReflect;\n"
814 "uniform vec4 ScreenCenterRefractReflect;\n"
815 "uniform vec4 RefractColor;\n"
816 "uniform vec4 ReflectColor;\n"
817 "uniform float ReflectFactor;\n"
818 "uniform float ReflectOffset;\n"
822 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
823 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
824 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
825 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
826 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
827 " // FIXME temporary hack to detect the case that the reflection\n"
828 " // gets blackened at edges due to leaving the area that contains actual\n"
830 " // Remove this 'ack once we have a better way to stop this thing from\n"
832 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
833 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
834 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
835 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
836 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
837 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
838 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
839 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
840 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
841 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
842 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
843 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
846 "#else // !MODE_WATER\n"
851 "// common definitions between vertex shader and fragment shader:\n"
853 "varying vec2 TexCoord;\n"
854 "#ifdef USEVERTEXTEXTUREBLEND\n"
855 "varying vec2 TexCoord2;\n"
857 "#ifdef USELIGHTMAP\n"
858 "varying vec2 TexCoordLightmap;\n"
861 "#ifdef MODE_LIGHTSOURCE\n"
862 "varying vec3 CubeVector;\n"
865 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
866 "varying vec3 LightVector;\n"
869 "#ifdef USEEYEVECTOR\n"
870 "varying vec3 EyeVector;\n"
873 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
876 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
877 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
878 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
879 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
882 "#ifdef USEREFLECTION\n"
883 "varying vec4 ModelViewProjectionPosition;\n"
885 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
886 "uniform vec3 LightPosition;\n"
887 "varying vec4 ModelViewPosition;\n"
890 "#ifdef MODE_LIGHTSOURCE\n"
891 "uniform vec3 LightPosition;\n"
893 "uniform vec3 EyePosition;\n"
894 "#ifdef MODE_LIGHTDIRECTION\n"
895 "uniform vec3 LightDir;\n"
897 "uniform vec4 FogPlane;\n"
903 "// 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"
905 "// fragment shader specific:\n"
906 "#ifdef FRAGMENT_SHADER\n"
908 "uniform sampler2D Texture_Normal;\n"
909 "uniform sampler2D Texture_Color;\n"
910 "uniform sampler2D Texture_Gloss;\n"
912 "uniform sampler2D Texture_Glow;\n"
914 "#ifdef USEVERTEXTEXTUREBLEND\n"
915 "uniform sampler2D Texture_SecondaryNormal;\n"
916 "uniform sampler2D Texture_SecondaryColor;\n"
917 "uniform sampler2D Texture_SecondaryGloss;\n"
919 "uniform sampler2D Texture_SecondaryGlow;\n"
922 "#ifdef USECOLORMAPPING\n"
923 "uniform sampler2D Texture_Pants;\n"
924 "uniform sampler2D Texture_Shirt;\n"
927 "uniform sampler2D Texture_FogMask;\n"
929 "#ifdef USELIGHTMAP\n"
930 "uniform sampler2D Texture_Lightmap;\n"
932 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
933 "uniform sampler2D Texture_Deluxemap;\n"
935 "#ifdef USEREFLECTION\n"
936 "uniform sampler2D Texture_Reflection;\n"
939 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
940 "uniform sampler2D Texture_ScreenDepth;\n"
941 "uniform sampler2D Texture_ScreenNormalMap;\n"
943 "#ifdef USEDEFERREDLIGHTMAP\n"
944 "uniform sampler2D Texture_ScreenDiffuse;\n"
945 "uniform sampler2D Texture_ScreenSpecular;\n"
948 "uniform myhalf3 Color_Pants;\n"
949 "uniform myhalf3 Color_Shirt;\n"
950 "uniform myhalf3 FogColor;\n"
953 "uniform float FogRangeRecip;\n"
954 "uniform float FogPlaneViewDist;\n"
955 "uniform float FogHeightFade;\n"
956 "float FogVertex(void)\n"
958 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
959 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
961 "#ifdef USEFOGOUTSIDE\n"
962 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
964 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
966 " return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
970 "#ifdef USEOFFSETMAPPING\n"
971 "uniform float OffsetMapping_Scale;\n"
972 "vec2 OffsetMapping(vec2 TexCoord)\n"
974 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
975 " // 14 sample relief mapping: linear search and then binary search\n"
976 " // this basically steps forward a small amount repeatedly until it finds\n"
977 " // itself inside solid, then jitters forward and back using decreasing\n"
978 " // amounts to find the impact\n"
979 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
980 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
981 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
982 " vec3 RT = vec3(TexCoord, 1);\n"
983 " OffsetVector *= 0.1;\n"
984 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
985 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
986 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
987 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
988 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
989 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
990 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
991 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
992 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
993 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
994 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
995 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
996 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
997 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1000 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1001 " // this basically moves forward the full distance, and then backs up based\n"
1002 " // on height of samples\n"
1003 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1004 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1005 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1006 " TexCoord += OffsetVector;\n"
1007 " OffsetVector *= 0.333;\n"
1008 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1009 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1010 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1011 " return TexCoord;\n"
1014 "#endif // USEOFFSETMAPPING\n"
1016 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1017 "uniform sampler2D Texture_Attenuation;\n"
1018 "uniform samplerCube Texture_Cube;\n"
1020 "#ifdef USESHADOWMAPRECT\n"
1021 "# ifdef USESHADOWSAMPLER\n"
1022 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1024 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1028 "#ifdef USESHADOWMAP2D\n"
1029 "# ifdef USESHADOWSAMPLER\n"
1030 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1032 "uniform sampler2D Texture_ShadowMap2D;\n"
1036 "#ifdef USESHADOWMAPVSDCT\n"
1037 "uniform samplerCube Texture_CubeProjection;\n"
1040 "#ifdef USESHADOWMAPCUBE\n"
1041 "# ifdef USESHADOWSAMPLER\n"
1042 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1044 "uniform samplerCube Texture_ShadowMapCube;\n"
1048 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1049 "uniform vec2 ShadowMap_TextureScale;\n"
1050 "uniform vec4 ShadowMap_Parameters;\n"
1053 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1054 "# ifndef USESHADOWMAPVSDCT\n"
1055 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1057 " vec3 adir = abs(dir);\n"
1061 " if (adir.x > adir.y)\n"
1063 " if (adir.x > adir.z) // X\n"
1067 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1073 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1078 " if (adir.y > adir.z) // Y\n"
1082 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1088 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1092 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1093 " stc.xy += offset * ShadowMap_Parameters.y;\n"
1094 " stc.z += ShadowMap_Parameters.z;\n"
1098 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1100 " vec3 adir = abs(dir);\n"
1101 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1102 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1103 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1104 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1105 " stc.z += ShadowMap_Parameters.z;\n"
1109 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1111 "#ifdef USESHADOWMAPCUBE\n"
1112 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1114 " vec3 adir = abs(dir);\n"
1115 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1119 "# ifdef USESHADOWMAPRECT\n"
1120 "float ShadowMapCompare(vec3 dir)\n"
1122 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1124 "# ifdef USESHADOWSAMPLER\n"
1126 "# ifdef USESHADOWMAPPCF\n"
1127 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1128 " 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"
1130 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1135 "# ifdef USESHADOWMAPPCF\n"
1136 "# if USESHADOWMAPPCF > 1\n"
1137 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1138 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1139 " 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"
1140 " 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"
1141 " 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"
1142 " 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"
1143 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1144 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1146 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1147 " vec2 offset = fract(shadowmaptc.xy);\n"
1148 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1149 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1150 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1151 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1152 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1155 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1163 "# ifdef USESHADOWMAP2D\n"
1164 "float ShadowMapCompare(vec3 dir)\n"
1166 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1169 "# ifdef USESHADOWSAMPLER\n"
1170 "# ifdef USESHADOWMAPPCF\n"
1171 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1172 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1173 " 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"
1175 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1178 "# ifdef USESHADOWMAPPCF\n"
1179 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1180 "# ifdef GL_ARB_texture_gather\n"
1181 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1183 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1185 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1186 " center *= ShadowMap_TextureScale;\n"
1187 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1188 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1189 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1190 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1191 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1192 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1193 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1195 "# ifdef GL_EXT_gpu_shader4\n"
1196 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1198 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1200 "# if USESHADOWMAPPCF > 1\n"
1201 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1202 " center *= ShadowMap_TextureScale;\n"
1203 " 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"
1204 " 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"
1205 " 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"
1206 " 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"
1207 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1208 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1210 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1211 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1212 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1213 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1214 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1215 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1219 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1226 "# ifdef USESHADOWMAPCUBE\n"
1227 "float ShadowMapCompare(vec3 dir)\n"
1229 " // apply depth texture cubemap as light filter\n"
1230 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1232 "# ifdef USESHADOWSAMPLER\n"
1233 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1235 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1240 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1241 "#endif // FRAGMENT_SHADER\n"
1246 "#ifdef MODE_DEFERREDGEOMETRY\n"
1247 "#ifdef VERTEX_SHADER\n"
1248 "uniform mat4 TexMatrix;\n"
1249 "#ifdef USEVERTEXTEXTUREBLEND\n"
1250 "uniform mat4 BackgroundTexMatrix;\n"
1252 "uniform mat4 ModelViewMatrix;\n"
1255 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1256 "#ifdef USEVERTEXTEXTUREBLEND\n"
1257 " gl_FrontColor = gl_Color;\n"
1258 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1261 " // transform unnormalized eye direction into tangent space\n"
1262 "#ifdef USEOFFSETMAPPING\n"
1263 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1264 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1265 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1266 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1269 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1270 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1271 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1272 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1274 "#endif // VERTEX_SHADER\n"
1276 "#ifdef FRAGMENT_SHADER\n"
1279 "#ifdef USEOFFSETMAPPING\n"
1280 " // apply offsetmapping\n"
1281 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1282 "#define TexCoord TexCoordOffset\n"
1285 "#ifdef USEALPHAKILL\n"
1286 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1290 "#ifdef USEVERTEXTEXTUREBLEND\n"
1291 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1292 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1293 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1294 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1297 "#ifdef USEVERTEXTEXTUREBLEND\n"
1298 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1299 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1301 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1302 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1305 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1307 "#endif // FRAGMENT_SHADER\n"
1308 "#else // !MODE_DEFERREDGEOMETRY\n"
1313 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1314 "#ifdef VERTEX_SHADER\n"
1315 "uniform mat4 ModelViewMatrix;\n"
1318 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1319 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1321 "#endif // VERTEX_SHADER\n"
1323 "#ifdef FRAGMENT_SHADER\n"
1324 "uniform mat4 ViewToLight;\n"
1325 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1326 "uniform vec2 ScreenToDepth;\n"
1327 "uniform myhalf3 DeferredColor_Ambient;\n"
1328 "uniform myhalf3 DeferredColor_Diffuse;\n"
1329 "#ifdef USESPECULAR\n"
1330 "uniform myhalf3 DeferredColor_Specular;\n"
1331 "uniform myhalf SpecularPower;\n"
1333 "uniform myhalf2 PixelToScreenTexCoord;\n"
1336 " // calculate viewspace pixel position\n"
1337 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1339 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1340 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1341 " // decode viewspace pixel normal\n"
1342 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1343 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1344 " // surfacenormal = pixel normal in viewspace\n"
1345 " // LightVector = pixel to light in viewspace\n"
1346 " // CubeVector = position in lightspace\n"
1347 " // eyevector = pixel to view in viewspace\n"
1348 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1349 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1350 "#ifdef USEDIFFUSE\n"
1351 " // calculate diffuse shading\n"
1352 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1353 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1355 "#ifdef USESPECULAR\n"
1356 " // calculate directional shading\n"
1357 " vec3 eyevector = position * -1.0;\n"
1358 "# ifdef USEEXACTSPECULARMATH\n"
1359 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1361 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1362 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1366 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1367 " fade *= ShadowMapCompare(CubeVector);\n"
1370 "#ifdef USEDIFFUSE\n"
1371 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1373 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1375 "#ifdef USESPECULAR\n"
1376 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1378 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1381 "# ifdef USECUBEFILTER\n"
1382 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1383 " gl_FragData[0].rgb *= cubecolor;\n"
1384 " gl_FragData[1].rgb *= cubecolor;\n"
1387 "#endif // FRAGMENT_SHADER\n"
1388 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1393 "#ifdef VERTEX_SHADER\n"
1394 "uniform mat4 TexMatrix;\n"
1395 "#ifdef USEVERTEXTEXTUREBLEND\n"
1396 "uniform mat4 BackgroundTexMatrix;\n"
1398 "#ifdef MODE_LIGHTSOURCE\n"
1399 "uniform mat4 ModelToLight;\n"
1403 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1404 " gl_FrontColor = gl_Color;\n"
1406 " // copy the surface texcoord\n"
1407 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1408 "#ifdef USEVERTEXTEXTUREBLEND\n"
1409 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1411 "#ifdef USELIGHTMAP\n"
1412 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1415 "#ifdef MODE_LIGHTSOURCE\n"
1416 " // transform vertex position into light attenuation/cubemap space\n"
1417 " // (-1 to +1 across the light box)\n"
1418 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1420 "# ifdef USEDIFFUSE\n"
1421 " // transform unnormalized light direction into tangent space\n"
1422 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1423 " // normalize it per pixel)\n"
1424 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1425 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1426 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1427 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1431 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1432 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1433 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1434 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1437 " // transform unnormalized eye direction into tangent space\n"
1438 "#ifdef USEEYEVECTOR\n"
1439 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1440 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1441 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1442 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1446 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1447 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1450 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1451 " VectorS = gl_MultiTexCoord1.xyz;\n"
1452 " VectorT = gl_MultiTexCoord2.xyz;\n"
1453 " VectorR = gl_MultiTexCoord3.xyz;\n"
1456 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1457 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1459 "#ifdef USEREFLECTION\n"
1460 " ModelViewProjectionPosition = gl_Position;\n"
1463 "#endif // VERTEX_SHADER\n"
1468 "#ifdef FRAGMENT_SHADER\n"
1469 "#ifdef USEDEFERREDLIGHTMAP\n"
1470 "uniform myhalf2 PixelToScreenTexCoord;\n"
1471 "uniform myhalf3 DeferredMod_Diffuse;\n"
1472 "uniform myhalf3 DeferredMod_Specular;\n"
1474 "uniform myhalf3 Color_Ambient;\n"
1475 "uniform myhalf3 Color_Diffuse;\n"
1476 "uniform myhalf3 Color_Specular;\n"
1477 "uniform myhalf SpecularPower;\n"
1479 "uniform myhalf3 Color_Glow;\n"
1481 "uniform myhalf Alpha;\n"
1482 "#ifdef USEREFLECTION\n"
1483 "uniform vec4 DistortScaleRefractReflect;\n"
1484 "uniform vec4 ScreenScaleRefractReflect;\n"
1485 "uniform vec4 ScreenCenterRefractReflect;\n"
1486 "uniform myhalf4 ReflectColor;\n"
1488 "#ifdef USEREFLECTCUBE\n"
1489 "uniform mat4 ModelToReflectCube;\n"
1490 "uniform sampler2D Texture_ReflectMask;\n"
1491 "uniform samplerCube Texture_ReflectCube;\n"
1493 "#ifdef MODE_LIGHTDIRECTION\n"
1494 "uniform myhalf3 LightColor;\n"
1496 "#ifdef MODE_LIGHTSOURCE\n"
1497 "uniform myhalf3 LightColor;\n"
1501 "#ifdef USEOFFSETMAPPING\n"
1502 " // apply offsetmapping\n"
1503 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1504 "#define TexCoord TexCoordOffset\n"
1507 " // combine the diffuse textures (base, pants, shirt)\n"
1508 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1509 "#ifdef USEALPHAKILL\n"
1510 " if (color.a < 0.5)\n"
1513 " color.a *= Alpha;\n"
1514 "#ifdef USECOLORMAPPING\n"
1515 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1517 "#ifdef USEVERTEXTEXTUREBLEND\n"
1518 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1519 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1520 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1521 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1523 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1526 " // get the surface normal\n"
1527 "#ifdef USEVERTEXTEXTUREBLEND\n"
1528 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1530 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1533 " // get the material colors\n"
1534 " myhalf3 diffusetex = color.rgb;\n"
1535 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1536 "# ifdef USEVERTEXTEXTUREBLEND\n"
1537 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1539 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1543 "#ifdef USEREFLECTCUBE\n"
1544 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1545 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1546 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1547 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1553 "#ifdef MODE_LIGHTSOURCE\n"
1554 " // light source\n"
1555 "#ifdef USEDIFFUSE\n"
1556 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1557 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1558 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1559 "#ifdef USESPECULAR\n"
1560 "#ifdef USEEXACTSPECULARMATH\n"
1561 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1563 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1564 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1566 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1569 " color.rgb = diffusetex * Color_Ambient;\n"
1571 " color.rgb *= LightColor;\n"
1572 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1573 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1574 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1576 "# ifdef USECUBEFILTER\n"
1577 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1579 "#endif // MODE_LIGHTSOURCE\n"
1584 "#ifdef MODE_LIGHTDIRECTION\n"
1586 "#ifdef USEDIFFUSE\n"
1587 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1589 "#define lightcolor LightColor\n"
1590 "#endif // MODE_LIGHTDIRECTION\n"
1591 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1593 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1594 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1595 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1596 " // convert modelspace light vector to tangentspace\n"
1597 " myhalf3 lightnormal;\n"
1598 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1599 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1600 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1601 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1602 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1603 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1604 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1605 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1606 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1607 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1608 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1609 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1610 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1611 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1612 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1614 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1615 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1616 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1622 "#ifdef MODE_LIGHTMAP\n"
1623 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1624 "#endif // MODE_LIGHTMAP\n"
1625 "#ifdef MODE_VERTEXCOLOR\n"
1626 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1627 "#endif // MODE_VERTEXCOLOR\n"
1628 "#ifdef MODE_FLATCOLOR\n"
1629 " color.rgb = diffusetex * Color_Ambient;\n"
1630 "#endif // MODE_FLATCOLOR\n"
1636 "# ifdef USEDIFFUSE\n"
1637 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1638 "# ifdef USESPECULAR\n"
1639 "# ifdef USEEXACTSPECULARMATH\n"
1640 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1642 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1643 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1645 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1647 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1650 " color.rgb = diffusetex * Color_Ambient;\n"
1654 "#ifdef USEDEFERREDLIGHTMAP\n"
1655 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1656 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1657 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1661 "#ifdef USEVERTEXTEXTUREBLEND\n"
1662 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1664 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1669 "#ifdef MODE_LIGHTSOURCE\n"
1670 " color.rgb *= myhalf(FogVertex());\n"
1672 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1676 " // 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"
1677 "#ifdef USEREFLECTION\n"
1678 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1679 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1680 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1681 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1682 " // FIXME temporary hack to detect the case that the reflection\n"
1683 " // gets blackened at edges due to leaving the area that contains actual\n"
1685 " // Remove this 'ack once we have a better way to stop this thing from\n"
1687 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1688 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1689 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1690 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1691 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1692 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1695 " gl_FragColor = vec4(color);\n"
1697 "#endif // FRAGMENT_SHADER\n"
1699 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1700 "#endif // !MODE_DEFERREDGEOMETRY\n"
1701 "#endif // !MODE_WATER\n"
1702 "#endif // !MODE_REFRACTION\n"
1703 "#endif // !MODE_BLOOMBLUR\n"
1704 "#endif // !MODE_GENERIC\n"
1705 "#endif // !MODE_POSTPROCESS\n"
1706 "#endif // !MODE_SHOWDEPTH\n"
1707 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1711 =========================================================================================================================================================
1715 =========================================================================================================================================================
1719 =========================================================================================================================================================
1723 =========================================================================================================================================================
1727 =========================================================================================================================================================
1731 =========================================================================================================================================================
1735 =========================================================================================================================================================
1738 const char *builtincgshaderstring =
1739 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1740 "// written by Forest 'LordHavoc' Hale\n"
1741 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1743 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1746 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1747 "#define USELIGHTMAP\n"
1749 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1750 "#define USEEYEVECTOR\n"
1753 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1754 "#ifdef VERTEX_SHADER\n"
1757 "float4 gl_Vertex : POSITION,\n"
1758 "uniform float4x4 ModelViewProjectionMatrix,\n"
1759 "out float4 gl_Position : POSITION\n"
1762 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1765 "#else // !MODE_DEPTH_ORSHADOW\n"
1770 "#ifdef MODE_SHOWDEPTH\n"
1771 "#ifdef VERTEX_SHADER\n"
1774 "float4 gl_Vertex : POSITION,\n"
1775 "uniform float4x4 ModelViewProjectionMatrix,\n"
1776 "out float4 gl_Position : POSITION,\n"
1777 "out float4 gl_FrontColor : COLOR0\n"
1780 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1781 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1785 "#ifdef FRAGMENT_SHADER\n"
1788 "float4 gl_FrontColor : COLOR0,\n"
1789 "out float4 gl_FragColor : COLOR\n"
1792 " gl_FragColor = gl_FrontColor;\n"
1795 "#else // !MODE_SHOWDEPTH\n"
1800 "#ifdef MODE_POSTPROCESS\n"
1802 "#ifdef VERTEX_SHADER\n"
1805 "float4 gl_Vertex : POSITION,\n"
1806 "uniform float4x4 ModelViewProjectionMatrix,\n"
1807 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1808 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1809 "out float4 gl_Position : POSITION,\n"
1810 "out float2 TexCoord1 : TEXCOORD0,\n"
1811 "out float2 TexCoord2 : TEXCOORD1\n"
1814 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1815 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1817 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1822 "#ifdef FRAGMENT_SHADER\n"
1825 "float2 TexCoord1 : TEXCOORD0,\n"
1826 "float2 TexCoord2 : TEXCOORD1,\n"
1827 "uniform sampler2D Texture_First,\n"
1829 "uniform sampler2D Texture_Second,\n"
1831 "#ifdef USEGAMMARAMPS\n"
1832 "uniform sampler2D Texture_GammaRamps,\n"
1834 "#ifdef USESATURATION\n"
1835 "uniform float Saturation,\n"
1837 "#ifdef USEVIEWTINT\n"
1838 "uniform float4 ViewTintColor,\n"
1840 "uniform float4 UserVec1,\n"
1841 "uniform float4 UserVec2,\n"
1842 "uniform float4 UserVec3,\n"
1843 "uniform float4 UserVec4,\n"
1844 "uniform float ClientTime,\n"
1845 "uniform float2 PixelSize,\n"
1846 "out float4 gl_FragColor : COLOR\n"
1849 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1851 " gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1853 "#ifdef USEVIEWTINT\n"
1854 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1857 "#ifdef USEPOSTPROCESSING\n"
1858 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1859 "// 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"
1860 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1861 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1862 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1863 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1864 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1865 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1868 "#ifdef USESATURATION\n"
1869 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1870 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1871 " //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1872 " gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1875 "#ifdef USEGAMMARAMPS\n"
1876 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1877 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1878 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1882 "#else // !MODE_POSTPROCESS\n"
1887 "#ifdef MODE_GENERIC\n"
1888 "#ifdef VERTEX_SHADER\n"
1891 "float4 gl_Vertex : POSITION,\n"
1892 "uniform float4x4 ModelViewProjectionMatrix,\n"
1893 "float4 gl_Color : COLOR0,\n"
1894 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1895 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1896 "out float4 gl_Position : POSITION,\n"
1897 "out float4 gl_FrontColor : COLOR,\n"
1898 "out float2 TexCoord1 : TEXCOORD0,\n"
1899 "out float2 TexCoord2 : TEXCOORD1\n"
1902 " gl_FrontColor = gl_Color;\n"
1903 "#ifdef USEDIFFUSE\n"
1904 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1906 "#ifdef USESPECULAR\n"
1907 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1909 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1913 "#ifdef FRAGMENT_SHADER\n"
1917 "float4 gl_FrontColor : COLOR,\n"
1918 "float2 TexCoord1 : TEXCOORD0,\n"
1919 "float2 TexCoord2 : TEXCOORD1,\n"
1920 "#ifdef USEDIFFUSE\n"
1921 "uniform sampler2D Texture_First,\n"
1923 "#ifdef USESPECULAR\n"
1924 "uniform sampler2D Texture_Second,\n"
1926 "out float4 gl_FragColor : COLOR\n"
1929 " gl_FragColor = gl_FrontColor;\n"
1930 "#ifdef USEDIFFUSE\n"
1931 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1934 "#ifdef USESPECULAR\n"
1935 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1936 "# ifdef USECOLORMAPPING\n"
1937 " gl_FragColor *= tex2;\n"
1940 " gl_FragColor += tex2;\n"
1942 "# ifdef USEVERTEXTEXTUREBLEND\n"
1943 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1948 "#else // !MODE_GENERIC\n"
1953 "#ifdef MODE_BLOOMBLUR\n"
1954 "#ifdef VERTEX_SHADER\n"
1957 "float4 gl_Vertex : POSITION,\n"
1958 "uniform float4x4 ModelViewProjectionMatrix,\n"
1959 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1960 "out float4 gl_Position : POSITION,\n"
1961 "out float2 TexCoord : TEXCOORD0\n"
1964 " TexCoord = gl_MultiTexCoord0.xy;\n"
1965 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1969 "#ifdef FRAGMENT_SHADER\n"
1973 "float2 TexCoord : TEXCOORD0,\n"
1974 "uniform sampler2D Texture_First,\n"
1975 "uniform float4 BloomBlur_Parameters,\n"
1976 "out float4 gl_FragColor : COLOR\n"
1980 " float2 tc = TexCoord;\n"
1981 " float3 color = tex2D(Texture_First, tc).rgb;\n"
1982 " tc += BloomBlur_Parameters.xy;\n"
1983 " for (i = 1;i < SAMPLES;i++)\n"
1985 " color += tex2D(Texture_First, tc).rgb;\n"
1986 " tc += BloomBlur_Parameters.xy;\n"
1988 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1991 "#else // !MODE_BLOOMBLUR\n"
1992 "#ifdef MODE_REFRACTION\n"
1993 "#ifdef VERTEX_SHADER\n"
1996 "float4 gl_Vertex : POSITION,\n"
1997 "uniform float4x4 ModelViewProjectionMatrix,\n"
1998 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1999 "uniform float4x4 TexMatrix,\n"
2000 "uniform float3 EyePosition,\n"
2001 "out float4 gl_Position : POSITION,\n"
2002 "out float2 TexCoord : TEXCOORD0,\n"
2003 "out float3 EyeVector : TEXCOORD1,\n"
2004 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2007 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2008 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2009 " ModelViewProjectionPosition = gl_Position;\n"
2013 "#ifdef FRAGMENT_SHADER\n"
2016 "float2 TexCoord : TEXCOORD0,\n"
2017 "float3 EyeVector : TEXCOORD1,\n"
2018 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2019 "uniform sampler2D Texture_Normal,\n"
2020 "uniform sampler2D Texture_Refraction,\n"
2021 "uniform sampler2D Texture_Reflection,\n"
2022 "uniform float4 DistortScaleRefractReflect,\n"
2023 "uniform float4 ScreenScaleRefractReflect,\n"
2024 "uniform float4 ScreenCenterRefractReflect,\n"
2025 "uniform float4 RefractColor,\n"
2026 "out float4 gl_FragColor : COLOR\n"
2029 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2030 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2031 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2032 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2033 " // FIXME temporary hack to detect the case that the reflection\n"
2034 " // gets blackened at edges due to leaving the area that contains actual\n"
2036 " // Remove this 'ack once we have a better way to stop this thing from\n"
2038 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2039 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2040 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2041 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2042 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2043 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2046 "#else // !MODE_REFRACTION\n"
2051 "#ifdef MODE_WATER\n"
2052 "#ifdef VERTEX_SHADER\n"
2056 "float4 gl_Vertex : POSITION,\n"
2057 "uniform float4x4 ModelViewProjectionMatrix,\n"
2058 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2059 "uniform float4x4 TexMatrix,\n"
2060 "uniform float3 EyePosition,\n"
2061 "out float4 gl_Position : POSITION,\n"
2062 "out float2 TexCoord : TEXCOORD0,\n"
2063 "out float3 EyeVector : TEXCOORD1,\n"
2064 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2067 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2068 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2069 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2070 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2071 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2072 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2073 " ModelViewProjectionPosition = gl_Position;\n"
2077 "#ifdef FRAGMENT_SHADER\n"
2080 "float2 TexCoord : TEXCOORD0,\n"
2081 "float3 EyeVector : TEXCOORD1,\n"
2082 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2083 "uniform sampler2D Texture_Normal,\n"
2084 "uniform sampler2D Texture_Refraction,\n"
2085 "uniform sampler2D Texture_Reflection,\n"
2086 "uniform float4 DistortScaleRefractReflect,\n"
2087 "uniform float4 ScreenScaleRefractReflect,\n"
2088 "uniform float4 ScreenCenterRefractReflect,\n"
2089 "uniform float4 RefractColor,\n"
2090 "uniform float4 ReflectColor,\n"
2091 "uniform float ReflectFactor,\n"
2092 "uniform float ReflectOffset,\n"
2093 "out float4 gl_FragColor : COLOR\n"
2096 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2097 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2098 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2099 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2100 " // FIXME temporary hack to detect the case that the reflection\n"
2101 " // gets blackened at edges due to leaving the area that contains actual\n"
2103 " // Remove this 'ack once we have a better way to stop this thing from\n"
2105 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2106 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2107 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2108 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2109 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2110 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2111 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2112 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2113 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2114 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2115 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2116 " gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2119 "#else // !MODE_WATER\n"
2124 "// 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"
2126 "// fragment shader specific:\n"
2127 "#ifdef FRAGMENT_SHADER\n"
2130 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2133 "#ifdef USEFOGOUTSIDE\n"
2134 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2136 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2138 " return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2142 "#ifdef USEOFFSETMAPPING\n"
2143 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2145 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2146 " // 14 sample relief mapping: linear search and then binary search\n"
2147 " // this basically steps forward a small amount repeatedly until it finds\n"
2148 " // itself inside solid, then jitters forward and back using decreasing\n"
2149 " // amounts to find the impact\n"
2150 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2151 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2152 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2153 " float3 RT = float3(TexCoord, 1);\n"
2154 " OffsetVector *= 0.1;\n"
2155 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2156 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2157 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2158 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2159 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2160 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2161 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2162 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2163 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2164 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2165 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2166 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2167 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2168 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2171 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2172 " // this basically moves forward the full distance, and then backs up based\n"
2173 " // on height of samples\n"
2174 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2175 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2176 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2177 " TexCoord += OffsetVector;\n"
2178 " OffsetVector *= 0.333;\n"
2179 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2180 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2181 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2182 " return TexCoord;\n"
2185 "#endif // USEOFFSETMAPPING\n"
2187 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2188 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2189 "# ifndef USESHADOWMAPVSDCT\n"
2190 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2192 " float3 adir = abs(dir);\n"
2196 " if (adir.x > adir.y)\n"
2198 " if (adir.x > adir.z) // X\n"
2202 " offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2208 " offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2213 " if (adir.y > adir.z) // Y\n"
2217 " offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2223 " offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2227 " float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2228 " stc.xy += offset * ShadowMap_Parameters.y;\n"
2229 " stc.z += ShadowMap_Parameters.z;\n"
2233 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2235 " float3 adir = abs(dir);\n"
2236 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2237 " float ma = max(max(adir.x, adir.y), adir.z);\n"
2238 " float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2239 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2240 " stc.z += ShadowMap_Parameters.z;\n"
2244 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2246 "#ifdef USESHADOWMAPCUBE\n"
2247 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2249 " float3 adir = abs(dir);\n"
2250 " return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2254 "# ifdef USESHADOWMAPRECT\n"
2255 "#ifdef USESHADOWMAPVSDCT\n"
2256 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2258 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2261 "#ifdef USESHADOWMAPVSDCT\n"
2262 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2264 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2267 "# ifdef USESHADOWSAMPLER\n"
2269 "# ifdef USESHADOWMAPPCF\n"
2270 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2271 " 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"
2273 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2278 "# ifdef USESHADOWMAPPCF\n"
2279 "# if USESHADOWMAPPCF > 1\n"
2280 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2281 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2282 " 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"
2283 " 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"
2284 " 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"
2285 " 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"
2286 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2287 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2289 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2290 " float2 offset = frac(shadowmaptc.xy);\n"
2291 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2292 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2293 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2294 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2295 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2298 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2306 "# ifdef USESHADOWMAP2D\n"
2307 "#ifdef USESHADOWMAPVSDCT\n"
2308 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2310 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2313 "#ifdef USESHADOWMAPVSDCT\n"
2314 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2316 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2320 "# ifdef USESHADOWSAMPLER\n"
2321 "# ifdef USESHADOWMAPPCF\n"
2322 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
2323 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2324 " 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"
2326 " f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2329 "# ifdef USESHADOWMAPPCF\n"
2330 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2331 "# ifdef GL_ARB_texture_gather\n"
2332 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2334 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2336 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2337 " center *= ShadowMap_TextureScale;\n"
2338 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2339 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2340 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2341 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2342 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2343 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2344 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2346 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale) \n"
2347 "# if USESHADOWMAPPCF > 1\n"
2348 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2349 " center *= ShadowMap_TextureScale;\n"
2350 " 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"
2351 " 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"
2352 " 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"
2353 " 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"
2354 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2355 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2357 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2358 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2359 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2360 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2361 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2362 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2366 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2373 "# ifdef USESHADOWMAPCUBE\n"
2374 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2376 " // apply depth texture cubemap as light filter\n"
2377 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2379 "# ifdef USESHADOWSAMPLER\n"
2380 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2382 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2387 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2388 "#endif // FRAGMENT_SHADER\n"
2393 "#ifdef MODE_DEFERREDGEOMETRY\n"
2394 "#ifdef VERTEX_SHADER\n"
2397 "float4 gl_Vertex : POSITION,\n"
2398 "uniform float4x4 ModelViewProjectionMatrix,\n"
2399 "#ifdef USEVERTEXTEXTUREBLEND\n"
2400 "float4 gl_Color : COLOR0,\n"
2402 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2403 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2404 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2405 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2406 "uniform float4x4 TexMatrix,\n"
2407 "#ifdef USEVERTEXTEXTUREBLEND\n"
2408 "uniform float4x4 BackgroundTexMatrix,\n"
2410 "uniform float4x4 ModelViewMatrix,\n"
2411 "#ifdef USEOFFSETMAPPING\n"
2412 "uniform float3 EyePosition,\n"
2414 "out float4 gl_Position : POSITION,\n"
2415 "out float4 gl_FrontColor : COLOR,\n"
2416 "out float4 TexCoordBoth : TEXCOORD0,\n"
2417 "#ifdef USEOFFSETMAPPING\n"
2418 "out float3 EyeVector : TEXCOORD2,\n"
2420 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2421 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2422 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2425 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2426 "#ifdef USEVERTEXTEXTUREBLEND\n"
2427 " gl_FrontColor = gl_Color;\n"
2428 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2431 " // transform unnormalized eye direction into tangent space\n"
2432 "#ifdef USEOFFSETMAPPING\n"
2433 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2434 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2435 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2436 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2439 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2440 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2441 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2442 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2444 "#endif // VERTEX_SHADER\n"
2446 "#ifdef FRAGMENT_SHADER\n"
2449 "float4 TexCoordBoth : TEXCOORD0,\n"
2450 "float3 EyeVector : TEXCOORD2,\n"
2451 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2452 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2453 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2454 "uniform sampler2D Texture_Normal,\n"
2455 "#ifdef USEALPHAKILL\n"
2456 "uniform sampler2D Texture_Color,\n"
2458 "uniform sampler2D Texture_Gloss,\n"
2459 "#ifdef USEVERTEXTEXTUREBLEND\n"
2460 "uniform sampler2D Texture_SecondaryNormal,\n"
2461 "uniform sampler2D Texture_SecondaryGloss,\n"
2463 "#ifdef USEOFFSETMAPPING\n"
2464 "uniform float OffsetMapping_Scale,\n"
2466 "uniform half SpecularPower,\n"
2467 "out float4 gl_FragColor : COLOR\n"
2470 " float2 TexCoord = TexCoordBoth.xy;\n"
2471 "#ifdef USEOFFSETMAPPING\n"
2472 " // apply offsetmapping\n"
2473 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2474 "#define TexCoord TexCoordOffset\n"
2477 "#ifdef USEALPHAKILL\n"
2478 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2482 "#ifdef USEVERTEXTEXTUREBLEND\n"
2483 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2484 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2485 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2486 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2489 "#ifdef USEVERTEXTEXTUREBLEND\n"
2490 " float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2491 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2493 " float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2494 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2497 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2499 "#endif // FRAGMENT_SHADER\n"
2500 "#else // !MODE_DEFERREDGEOMETRY\n"
2505 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2506 "#ifdef VERTEX_SHADER\n"
2509 "float4 gl_Vertex : POSITION,\n"
2510 "uniform float4x4 ModelViewProjectionMatrix,\n"
2511 "uniform float4x4 ModelViewMatrix,\n"
2512 "out float4 gl_Position : POSITION,\n"
2513 "out float4 ModelViewPosition : TEXCOORD0\n"
2516 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2517 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2519 "#endif // VERTEX_SHADER\n"
2521 "#ifdef FRAGMENT_SHADER\n"
2524 "float2 Pixel : WPOS,\n"
2525 "float4 ModelViewPosition : TEXCOORD0,\n"
2526 "uniform float4x4 ViewToLight,\n"
2527 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2528 "uniform float3 LightPosition,\n"
2529 "uniform half2 PixelToScreenTexCoord,\n"
2530 "uniform half3 DeferredColor_Ambient,\n"
2531 "uniform half3 DeferredColor_Diffuse,\n"
2532 "#ifdef USESPECULAR\n"
2533 "uniform half3 DeferredColor_Specular,\n"
2534 "uniform half SpecularPower,\n"
2536 "uniform sampler2D Texture_Attenuation,\n"
2537 "uniform sampler2D Texture_ScreenDepth,\n"
2538 "uniform sampler2D Texture_ScreenNormalMap,\n"
2540 "#ifdef USESHADOWMAPRECT\n"
2541 "# ifdef USESHADOWSAMPLER\n"
2542 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2544 "uniform samplerRECT Texture_ShadowMapRect,\n"
2548 "#ifdef USESHADOWMAP2D\n"
2549 "# ifdef USESHADOWSAMPLER\n"
2550 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2552 "uniform sampler2D Texture_ShadowMap2D,\n"
2556 "#ifdef USESHADOWMAPVSDCT\n"
2557 "uniform samplerCUBE Texture_CubeProjection,\n"
2560 "#ifdef USESHADOWMAPCUBE\n"
2561 "# ifdef USESHADOWSAMPLER\n"
2562 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2564 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2568 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2569 "uniform float2 ShadowMap_TextureScale,\n"
2570 "uniform float4 ShadowMap_Parameters,\n"
2573 "out float4 gl_FragData0 : COLOR0,\n"
2574 "out float4 gl_FragData1 : COLOR1\n"
2577 " // calculate viewspace pixel position\n"
2578 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2579 " ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2580 " float3 position;\n"
2581 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2582 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2583 " // decode viewspace pixel normal\n"
2584 " half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2585 " half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2586 " // surfacenormal = pixel normal in viewspace\n"
2587 " // LightVector = pixel to light in viewspace\n"
2588 " // CubeVector = position in lightspace\n"
2589 " // eyevector = pixel to view in viewspace\n"
2590 " float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2591 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2592 "#ifdef USEDIFFUSE\n"
2593 " // calculate diffuse shading\n"
2594 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2595 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2597 "#ifdef USESPECULAR\n"
2598 " // calculate directional shading\n"
2599 " float3 eyevector = position * -1.0;\n"
2600 "# ifdef USEEXACTSPECULARMATH\n"
2601 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2603 " half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2604 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2608 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2609 " fade *= ShadowMapCompare(CubeVector,\n"
2610 "# if defined(USESHADOWMAP2D)\n"
2611 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2613 "# if defined(USESHADOWMAPRECT)\n"
2614 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2616 "# if defined(USESHADOWMAPCUBE)\n"
2617 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2620 "#ifdef USESHADOWMAPVSDCT\n"
2621 ", Texture_CubeProjection\n"
2626 "#ifdef USEDIFFUSE\n"
2627 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2629 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2631 "#ifdef USESPECULAR\n"
2632 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2634 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2637 "# ifdef USECUBEFILTER\n"
2638 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2639 " gl_FragData0.rgb *= cubecolor;\n"
2640 " gl_FragData1.rgb *= cubecolor;\n"
2643 "#endif // FRAGMENT_SHADER\n"
2644 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2649 "#ifdef VERTEX_SHADER\n"
2652 "float4 gl_Vertex : POSITION,\n"
2653 "uniform float4x4 ModelViewProjectionMatrix,\n"
2654 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2655 "float4 gl_Color : COLOR0,\n"
2657 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2658 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2659 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2660 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2661 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2663 "uniform float3 EyePosition,\n"
2664 "uniform float4x4 TexMatrix,\n"
2665 "#ifdef USEVERTEXTEXTUREBLEND\n"
2666 "uniform float4x4 BackgroundTexMatrix,\n"
2668 "#ifdef MODE_LIGHTSOURCE\n"
2669 "uniform float4x4 ModelToLight,\n"
2671 "#ifdef MODE_LIGHTSOURCE\n"
2672 "uniform float3 LightPosition,\n"
2674 "#ifdef MODE_LIGHTDIRECTION\n"
2675 "uniform float3 LightDir,\n"
2677 "uniform float4 FogPlane,\n"
2678 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2679 "uniform float3 LightPosition,\n"
2682 "out float4 gl_FrontColor : COLOR,\n"
2683 "out float4 TexCoordBoth : TEXCOORD0,\n"
2684 "#ifdef USELIGHTMAP\n"
2685 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2687 "#ifdef USEEYEVECTOR\n"
2688 "out float3 EyeVector : TEXCOORD2,\n"
2690 "#ifdef USEREFLECTION\n"
2691 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2694 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2696 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2697 "out float3 LightVector : TEXCOORD5,\n"
2699 "#ifdef MODE_LIGHTSOURCE\n"
2700 "out float3 CubeVector : TEXCOORD3,\n"
2702 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2703 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2704 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2705 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2707 "out float4 gl_Position : POSITION\n"
2710 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2711 " gl_FrontColor = gl_Color;\n"
2713 " // copy the surface texcoord\n"
2714 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2715 "#ifdef USEVERTEXTEXTUREBLEND\n"
2716 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2718 "#ifdef USELIGHTMAP\n"
2719 " TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2722 "#ifdef MODE_LIGHTSOURCE\n"
2723 " // transform vertex position into light attenuation/cubemap space\n"
2724 " // (-1 to +1 across the light box)\n"
2725 " CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2727 "# ifdef USEDIFFUSE\n"
2728 " // transform unnormalized light direction into tangent space\n"
2729 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2730 " // normalize it per pixel)\n"
2731 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2732 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2733 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2734 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2738 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2739 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2740 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2741 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2744 " // transform unnormalized eye direction into tangent space\n"
2745 "#ifdef USEEYEVECTOR\n"
2746 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2747 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2748 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2749 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2753 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2754 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2757 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2758 " VectorS = gl_MultiTexCoord1.xyz;\n"
2759 " VectorT = gl_MultiTexCoord2.xyz;\n"
2760 " VectorR = gl_MultiTexCoord3.xyz;\n"
2763 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2764 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2766 "#ifdef USEREFLECTION\n"
2767 " ModelViewProjectionPosition = gl_Position;\n"
2770 "#endif // VERTEX_SHADER\n"
2775 "#ifdef FRAGMENT_SHADER\n"
2778 "#ifdef USEDEFERREDLIGHTMAP\n"
2779 "float2 Pixel : WPOS,\n"
2781 "float4 gl_FrontColor : COLOR,\n"
2782 "float4 TexCoordBoth : TEXCOORD0,\n"
2783 "#ifdef USELIGHTMAP\n"
2784 "float2 TexCoordLightmap : TEXCOORD1,\n"
2786 "#ifdef USEEYEVECTOR\n"
2787 "float3 EyeVector : TEXCOORD2,\n"
2789 "#ifdef USEREFLECTION\n"
2790 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2793 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2795 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2796 "float3 LightVector : TEXCOORD5,\n"
2798 "#ifdef MODE_LIGHTSOURCE\n"
2799 "float3 CubeVector : TEXCOORD3,\n"
2801 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2802 "float4 ModelViewPosition : TEXCOORD0,\n"
2804 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2805 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2806 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2807 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2810 "uniform sampler2D Texture_Normal,\n"
2811 "uniform sampler2D Texture_Color,\n"
2812 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2813 "uniform sampler2D Texture_Gloss,\n"
2816 "uniform sampler2D Texture_Glow,\n"
2818 "#ifdef USEVERTEXTEXTUREBLEND\n"
2819 "uniform sampler2D Texture_SecondaryNormal,\n"
2820 "uniform sampler2D Texture_SecondaryColor,\n"
2821 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2822 "uniform sampler2D Texture_SecondaryGloss,\n"
2825 "uniform sampler2D Texture_SecondaryGlow,\n"
2828 "#ifdef USECOLORMAPPING\n"
2829 "uniform sampler2D Texture_Pants,\n"
2830 "uniform sampler2D Texture_Shirt,\n"
2833 "uniform sampler2D Texture_FogMask,\n"
2835 "#ifdef USELIGHTMAP\n"
2836 "uniform sampler2D Texture_Lightmap,\n"
2838 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2839 "uniform sampler2D Texture_Deluxemap,\n"
2841 "#ifdef USEREFLECTION\n"
2842 "uniform sampler2D Texture_Reflection,\n"
2845 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2846 "uniform sampler2D Texture_ScreenDepth,\n"
2847 "uniform sampler2D Texture_ScreenNormalMap,\n"
2849 "#ifdef USEDEFERREDLIGHTMAP\n"
2850 "uniform sampler2D Texture_ScreenDiffuse,\n"
2851 "uniform sampler2D Texture_ScreenSpecular,\n"
2854 "#ifdef USECOLORMAPPING\n"
2855 "uniform half3 Color_Pants,\n"
2856 "uniform half3 Color_Shirt,\n"
2859 "uniform float3 FogColor,\n"
2860 "uniform float FogRangeRecip,\n"
2861 "uniform float FogPlaneViewDist,\n"
2862 "uniform float FogHeightFade,\n"
2865 "#ifdef USEOFFSETMAPPING\n"
2866 "uniform float OffsetMapping_Scale,\n"
2869 "#ifdef USEDEFERREDLIGHTMAP\n"
2870 "uniform half2 PixelToScreenTexCoord,\n"
2871 "uniform half3 DeferredMod_Diffuse,\n"
2872 "uniform half3 DeferredMod_Specular,\n"
2874 "uniform half3 Color_Ambient,\n"
2875 "uniform half3 Color_Diffuse,\n"
2876 "uniform half3 Color_Specular,\n"
2877 "uniform half SpecularPower,\n"
2879 "uniform half3 Color_Glow,\n"
2881 "uniform half Alpha,\n"
2882 "#ifdef USEREFLECTION\n"
2883 "uniform float4 DistortScaleRefractReflect,\n"
2884 "uniform float4 ScreenScaleRefractReflect,\n"
2885 "uniform float4 ScreenCenterRefractReflect,\n"
2886 "uniform half4 ReflectColor,\n"
2888 "#ifdef USEREFLECTCUBE\n"
2889 "uniform float4x4 ModelToReflectCube,\n"
2890 "uniform sampler2D Texture_ReflectMask,\n"
2891 "uniform samplerCUBE Texture_ReflectCube,\n"
2893 "#ifdef MODE_LIGHTDIRECTION\n"
2894 "uniform half3 LightColor,\n"
2896 "#ifdef MODE_LIGHTSOURCE\n"
2897 "uniform half3 LightColor,\n"
2900 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2901 "uniform sampler2D Texture_Attenuation,\n"
2902 "uniform samplerCUBE Texture_Cube,\n"
2904 "#ifdef USESHADOWMAPRECT\n"
2905 "# ifdef USESHADOWSAMPLER\n"
2906 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2908 "uniform samplerRECT Texture_ShadowMapRect,\n"
2912 "#ifdef USESHADOWMAP2D\n"
2913 "# ifdef USESHADOWSAMPLER\n"
2914 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2916 "uniform sampler2D Texture_ShadowMap2D,\n"
2920 "#ifdef USESHADOWMAPVSDCT\n"
2921 "uniform samplerCUBE Texture_CubeProjection,\n"
2924 "#ifdef USESHADOWMAPCUBE\n"
2925 "# ifdef USESHADOWSAMPLER\n"
2926 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2928 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2932 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2933 "uniform float2 ShadowMap_TextureScale,\n"
2934 "uniform float4 ShadowMap_Parameters,\n"
2936 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2938 "out float4 gl_FragColor : COLOR\n"
2941 " float2 TexCoord = TexCoordBoth.xy;\n"
2942 "#ifdef USEVERTEXTEXTUREBLEND\n"
2943 " float2 TexCoord2 = TexCoordBoth.zw;\n"
2945 "#ifdef USEOFFSETMAPPING\n"
2946 " // apply offsetmapping\n"
2947 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2948 "#define TexCoord TexCoordOffset\n"
2951 " // combine the diffuse textures (base, pants, shirt)\n"
2952 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2953 "#ifdef USEALPHAKILL\n"
2954 " if (color.a < 0.5)\n"
2957 " color.a *= Alpha;\n"
2958 "#ifdef USECOLORMAPPING\n"
2959 " color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2961 "#ifdef USEVERTEXTEXTUREBLEND\n"
2962 " float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2963 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2964 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2965 " color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2967 " //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2970 " // get the surface normal\n"
2971 "#ifdef USEVERTEXTEXTUREBLEND\n"
2972 " half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2974 " half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2977 " // get the material colors\n"
2978 " half3 diffusetex = color.rgb;\n"
2979 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2980 "# ifdef USEVERTEXTEXTUREBLEND\n"
2981 " half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2983 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
2987 "#ifdef USEREFLECTCUBE\n"
2988 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
2989 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
2990 " vec3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
2991 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
2997 "#ifdef MODE_LIGHTSOURCE\n"
2998 " // light source\n"
2999 "#ifdef USEDIFFUSE\n"
3000 " half3 lightnormal = half3(normalize(LightVector));\n"
3001 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3002 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3003 "#ifdef USESPECULAR\n"
3004 "#ifdef USEEXACTSPECULARMATH\n"
3005 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3007 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3008 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3010 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3013 " color.rgb = diffusetex * Color_Ambient;\n"
3015 " color.rgb *= LightColor;\n"
3016 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3017 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3018 " color.rgb *= ShadowMapCompare(CubeVector,\n"
3019 "# if defined(USESHADOWMAP2D)\n"
3020 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3022 "# if defined(USESHADOWMAPRECT)\n"
3023 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3025 "# if defined(USESHADOWMAPCUBE)\n"
3026 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3029 "#ifdef USESHADOWMAPVSDCT\n"
3030 ", Texture_CubeProjection\n"
3035 "# ifdef USECUBEFILTER\n"
3036 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3038 "#endif // MODE_LIGHTSOURCE\n"
3043 "#ifdef MODE_LIGHTDIRECTION\n"
3045 "#ifdef USEDIFFUSE\n"
3046 " half3 lightnormal = half3(normalize(LightVector));\n"
3048 "#define lightcolor LightColor\n"
3049 "#endif // MODE_LIGHTDIRECTION\n"
3050 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3052 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3053 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3054 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3055 " // convert modelspace light vector to tangentspace\n"
3056 " half3 lightnormal;\n"
3057 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3058 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3059 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3060 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3061 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3062 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3063 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3064 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3065 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3066 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3067 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3068 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3069 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3070 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3071 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3073 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3074 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3075 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3081 "#ifdef MODE_LIGHTMAP\n"
3082 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3083 "#endif // MODE_LIGHTMAP\n"
3084 "#ifdef MODE_VERTEXCOLOR\n"
3085 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3086 "#endif // MODE_VERTEXCOLOR\n"
3087 "#ifdef MODE_FLATCOLOR\n"
3088 " color.rgb = diffusetex * Color_Ambient;\n"
3089 "#endif // MODE_FLATCOLOR\n"
3095 "# ifdef USEDIFFUSE\n"
3096 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3097 "# ifdef USESPECULAR\n"
3098 "# ifdef USEEXACTSPECULARMATH\n"
3099 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3101 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3102 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3104 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3106 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3109 " color.rgb = diffusetex * Color_Ambient;\n"
3113 "#ifdef USEDEFERREDLIGHTMAP\n"
3114 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3115 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3116 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3120 "#ifdef USEVERTEXTEXTUREBLEND\n"
3121 " color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3123 " color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3128 "#ifdef MODE_LIGHTSOURCE\n"
3129 " color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3131 " color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3135 " // 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"
3136 "#ifdef USEREFLECTION\n"
3137 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3138 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3139 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3140 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3141 " // FIXME temporary hack to detect the case that the reflection\n"
3142 " // gets blackened at edges due to leaving the area that contains actual\n"
3144 " // Remove this 'ack once we have a better way to stop this thing from\n"
3146 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3147 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3148 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3149 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3150 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3151 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3154 " gl_FragColor = float4(color);\n"
3156 "#endif // FRAGMENT_SHADER\n"
3158 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3159 "#endif // !MODE_DEFERREDGEOMETRY\n"
3160 "#endif // !MODE_WATER\n"
3161 "#endif // !MODE_REFRACTION\n"
3162 "#endif // !MODE_BLOOMBLUR\n"
3163 "#endif // !MODE_GENERIC\n"
3164 "#endif // !MODE_POSTPROCESS\n"
3165 "#endif // !MODE_SHOWDEPTH\n"
3166 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3169 char *glslshaderstring = NULL;
3170 char *cgshaderstring = NULL;
3172 //=======================================================================================================================================================
3174 typedef struct shaderpermutationinfo_s
3176 const char *pretext;
3179 shaderpermutationinfo_t;
3181 typedef struct shadermodeinfo_s
3183 const char *vertexfilename;
3184 const char *geometryfilename;
3185 const char *fragmentfilename;
3186 const char *pretext;
3191 typedef enum shaderpermutation_e
3193 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3194 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3195 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3196 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3197 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3198 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3199 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3200 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3201 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3202 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3203 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3204 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3205 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3206 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3207 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3208 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3209 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3210 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3211 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3212 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3213 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3214 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3215 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3216 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3217 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3218 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3219 SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3220 SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3221 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3223 shaderpermutation_t;
3225 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3226 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3228 {"#define USEDIFFUSE\n", " diffuse"},
3229 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3230 {"#define USEVIEWTINT\n", " viewtint"},
3231 {"#define USECOLORMAPPING\n", " colormapping"},
3232 {"#define USESATURATION\n", " saturation"},
3233 {"#define USEFOGINSIDE\n", " foginside"},
3234 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3235 {"#define USEGAMMARAMPS\n", " gammaramps"},
3236 {"#define USECUBEFILTER\n", " cubefilter"},
3237 {"#define USEGLOW\n", " glow"},
3238 {"#define USEBLOOM\n", " bloom"},
3239 {"#define USESPECULAR\n", " specular"},
3240 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3241 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3242 {"#define USEREFLECTION\n", " reflection"},
3243 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3244 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3245 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3246 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3247 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3248 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3249 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3250 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3251 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3252 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3253 {"#define USEALPHAKILL\n", " alphakill"},
3254 {"#define USEREFLECTCUBE\n", " reflectcube"},
3257 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3258 typedef enum shadermode_e
3260 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3261 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3262 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3263 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3264 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3265 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3266 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3267 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3268 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3269 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3270 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3271 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3272 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3273 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3274 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3279 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3280 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3282 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3283 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3284 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3285 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3286 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3287 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3288 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3289 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3290 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3291 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3292 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3293 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3294 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3295 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3296 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3300 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3302 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3303 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3304 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3305 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3306 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3307 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3308 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3309 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3310 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3311 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3312 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3313 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3314 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3315 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3316 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3320 struct r_glsl_permutation_s;
3321 typedef struct r_glsl_permutation_s
3323 /// hash lookup data
3324 struct r_glsl_permutation_s *hashnext;
3326 unsigned int permutation;
3328 /// indicates if we have tried compiling this permutation already
3330 /// 0 if compilation failed
3332 /// locations of detected uniforms in program object, or -1 if not found
3333 int loc_Texture_First;
3334 int loc_Texture_Second;
3335 int loc_Texture_GammaRamps;
3336 int loc_Texture_Normal;
3337 int loc_Texture_Color;
3338 int loc_Texture_Gloss;
3339 int loc_Texture_Glow;
3340 int loc_Texture_SecondaryNormal;
3341 int loc_Texture_SecondaryColor;
3342 int loc_Texture_SecondaryGloss;
3343 int loc_Texture_SecondaryGlow;
3344 int loc_Texture_Pants;
3345 int loc_Texture_Shirt;
3346 int loc_Texture_FogMask;
3347 int loc_Texture_Lightmap;
3348 int loc_Texture_Deluxemap;
3349 int loc_Texture_Attenuation;
3350 int loc_Texture_Cube;
3351 int loc_Texture_Refraction;
3352 int loc_Texture_Reflection;
3353 int loc_Texture_ShadowMapRect;
3354 int loc_Texture_ShadowMapCube;
3355 int loc_Texture_ShadowMap2D;
3356 int loc_Texture_CubeProjection;
3357 int loc_Texture_ScreenDepth;
3358 int loc_Texture_ScreenNormalMap;
3359 int loc_Texture_ScreenDiffuse;
3360 int loc_Texture_ScreenSpecular;
3361 int loc_Texture_ReflectMask;
3362 int loc_Texture_ReflectCube;
3364 int loc_BloomBlur_Parameters;
3366 int loc_Color_Ambient;
3367 int loc_Color_Diffuse;
3368 int loc_Color_Specular;
3370 int loc_Color_Pants;
3371 int loc_Color_Shirt;
3372 int loc_DeferredColor_Ambient;
3373 int loc_DeferredColor_Diffuse;
3374 int loc_DeferredColor_Specular;
3375 int loc_DeferredMod_Diffuse;
3376 int loc_DeferredMod_Specular;
3377 int loc_DistortScaleRefractReflect;
3378 int loc_EyePosition;
3380 int loc_FogHeightFade;
3382 int loc_FogPlaneViewDist;
3383 int loc_FogRangeRecip;
3386 int loc_LightPosition;
3387 int loc_OffsetMapping_Scale;
3389 int loc_ReflectColor;
3390 int loc_ReflectFactor;
3391 int loc_ReflectOffset;
3392 int loc_RefractColor;
3394 int loc_ScreenCenterRefractReflect;
3395 int loc_ScreenScaleRefractReflect;
3396 int loc_ScreenToDepth;
3397 int loc_ShadowMap_Parameters;
3398 int loc_ShadowMap_TextureScale;
3399 int loc_SpecularPower;
3404 int loc_ViewTintColor;
3405 int loc_ViewToLight;
3406 int loc_ModelToLight;
3408 int loc_BackgroundTexMatrix;
3409 int loc_ModelViewProjectionMatrix;
3410 int loc_ModelViewMatrix;
3411 int loc_PixelToScreenTexCoord;
3412 int loc_ModelToReflectCube;
3414 r_glsl_permutation_t;
3416 #define SHADERPERMUTATION_HASHSIZE 256
3418 /// information about each possible shader permutation
3419 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3420 /// currently selected permutation
3421 r_glsl_permutation_t *r_glsl_permutation;
3422 /// storage for permutations linked in the hash table
3423 memexpandablearray_t r_glsl_permutationarray;
3425 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3427 //unsigned int hashdepth = 0;
3428 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3429 r_glsl_permutation_t *p;
3430 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3432 if (p->mode == mode && p->permutation == permutation)
3434 //if (hashdepth > 10)
3435 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3440 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3442 p->permutation = permutation;
3443 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3444 r_glsl_permutationhash[mode][hashindex] = p;
3445 //if (hashdepth > 10)
3446 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3450 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3453 if (!filename || !filename[0])
3455 if (!strcmp(filename, "glsl/default.glsl"))
3457 if (!glslshaderstring)
3459 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3460 if (glslshaderstring)
3461 Con_DPrintf("Loading shaders from file %s...\n", filename);
3463 glslshaderstring = (char *)builtinshaderstring;
3465 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3466 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3467 return shaderstring;
3469 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3472 if (printfromdisknotice)
3473 Con_DPrintf("from disk %s... ", filename);
3474 return shaderstring;
3476 return shaderstring;
3479 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3482 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3483 int vertstrings_count = 0;
3484 int geomstrings_count = 0;
3485 int fragstrings_count = 0;
3486 char *vertexstring, *geometrystring, *fragmentstring;
3487 const char *vertstrings_list[32+3];
3488 const char *geomstrings_list[32+3];
3489 const char *fragstrings_list[32+3];
3490 char permutationname[256];
3497 permutationname[0] = 0;
3498 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3499 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3500 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3502 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3504 // the first pretext is which type of shader to compile as
3505 // (later these will all be bound together as a program object)
3506 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3507 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3508 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3510 // the second pretext is the mode (for example a light source)
3511 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3512 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3513 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3514 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3516 // now add all the permutation pretexts
3517 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3519 if (permutation & (1<<i))
3521 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3522 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3523 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3524 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3528 // keep line numbers correct
3529 vertstrings_list[vertstrings_count++] = "\n";
3530 geomstrings_list[geomstrings_count++] = "\n";
3531 fragstrings_list[fragstrings_count++] = "\n";
3535 // now append the shader text itself
3536 vertstrings_list[vertstrings_count++] = vertexstring;
3537 geomstrings_list[geomstrings_count++] = geometrystring;
3538 fragstrings_list[fragstrings_count++] = fragmentstring;
3540 // if any sources were NULL, clear the respective list
3542 vertstrings_count = 0;
3543 if (!geometrystring)
3544 geomstrings_count = 0;
3545 if (!fragmentstring)
3546 fragstrings_count = 0;
3548 // compile the shader program
3549 if (vertstrings_count + geomstrings_count + fragstrings_count)
3550 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3554 qglUseProgramObjectARB(p->program);CHECKGLERROR
3555 // look up all the uniform variable names we care about, so we don't
3556 // have to look them up every time we set them
3558 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3559 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3560 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3561 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3562 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3563 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3564 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3565 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3566 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3567 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3568 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3569 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3570 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3571 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3572 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3573 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3574 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3575 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3576 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3577 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3578 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3579 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3580 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3581 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3582 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3583 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3584 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3585 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3586 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3587 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3588 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3589 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3590 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3591 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3592 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3593 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3594 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3595 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3596 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3597 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3598 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3599 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3600 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3601 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3602 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3603 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3604 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3605 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3606 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3607 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3608 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3609 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3610 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3611 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3612 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3613 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3614 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3615 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3616 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3617 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3618 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3619 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3620 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3621 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3622 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3623 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3624 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3625 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3626 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3627 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3628 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3629 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3630 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3631 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3632 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3633 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3634 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3635 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3636 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3637 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3638 // initialize the samplers to refer to the texture units we use
3639 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3640 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3641 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3642 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3643 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3644 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3645 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3646 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3647 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3648 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3649 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3650 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3651 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3652 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3653 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3654 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3655 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3656 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3657 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3658 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3659 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
3660 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3661 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3662 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3663 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3664 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3665 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3666 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3667 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3668 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3670 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3673 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3677 Mem_Free(vertexstring);
3679 Mem_Free(geometrystring);
3681 Mem_Free(fragmentstring);
3684 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3686 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3687 if (r_glsl_permutation != perm)
3689 r_glsl_permutation = perm;
3690 if (!r_glsl_permutation->program)
3692 if (!r_glsl_permutation->compiled)
3693 R_GLSL_CompilePermutation(perm, mode, permutation);
3694 if (!r_glsl_permutation->program)
3696 // remove features until we find a valid permutation
3698 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3700 // reduce i more quickly whenever it would not remove any bits
3701 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3702 if (!(permutation & j))
3705 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3706 if (!r_glsl_permutation->compiled)
3707 R_GLSL_CompilePermutation(perm, mode, permutation);
3708 if (r_glsl_permutation->program)
3711 if (i >= SHADERPERMUTATION_COUNT)
3713 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3714 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3715 qglUseProgramObjectARB(0);CHECKGLERROR
3716 return; // no bit left to clear, entire mode is broken
3721 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3723 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3724 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3725 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3729 #include <Cg/cgGL.h>
3730 struct r_cg_permutation_s;
3731 typedef struct r_cg_permutation_s
3733 /// hash lookup data
3734 struct r_cg_permutation_s *hashnext;
3736 unsigned int permutation;
3738 /// indicates if we have tried compiling this permutation already
3740 /// 0 if compilation failed
3743 /// locations of detected parameters in programs, or NULL if not found
3744 CGparameter vp_EyePosition;
3745 CGparameter vp_FogPlane;
3746 CGparameter vp_LightDir;
3747 CGparameter vp_LightPosition;
3748 CGparameter vp_ModelToLight;
3749 CGparameter vp_TexMatrix;
3750 CGparameter vp_BackgroundTexMatrix;
3751 CGparameter vp_ModelViewProjectionMatrix;
3752 CGparameter vp_ModelViewMatrix;
3754 CGparameter fp_Texture_First;
3755 CGparameter fp_Texture_Second;
3756 CGparameter fp_Texture_GammaRamps;
3757 CGparameter fp_Texture_Normal;
3758 CGparameter fp_Texture_Color;
3759 CGparameter fp_Texture_Gloss;
3760 CGparameter fp_Texture_Glow;
3761 CGparameter fp_Texture_SecondaryNormal;
3762 CGparameter fp_Texture_SecondaryColor;
3763 CGparameter fp_Texture_SecondaryGloss;
3764 CGparameter fp_Texture_SecondaryGlow;
3765 CGparameter fp_Texture_Pants;
3766 CGparameter fp_Texture_Shirt;
3767 CGparameter fp_Texture_FogMask;
3768 CGparameter fp_Texture_Lightmap;
3769 CGparameter fp_Texture_Deluxemap;
3770 CGparameter fp_Texture_Attenuation;
3771 CGparameter fp_Texture_Cube;
3772 CGparameter fp_Texture_Refraction;
3773 CGparameter fp_Texture_Reflection;
3774 CGparameter fp_Texture_ShadowMapRect;
3775 CGparameter fp_Texture_ShadowMapCube;
3776 CGparameter fp_Texture_ShadowMap2D;
3777 CGparameter fp_Texture_CubeProjection;
3778 CGparameter fp_Texture_ScreenDepth;
3779 CGparameter fp_Texture_ScreenNormalMap;
3780 CGparameter fp_Texture_ScreenDiffuse;
3781 CGparameter fp_Texture_ScreenSpecular;
3782 CGparameter fp_Texture_ReflectMask;
3783 CGparameter fp_Texture_ReflectCube;
3784 CGparameter fp_Alpha;
3785 CGparameter fp_BloomBlur_Parameters;
3786 CGparameter fp_ClientTime;
3787 CGparameter fp_Color_Ambient;
3788 CGparameter fp_Color_Diffuse;
3789 CGparameter fp_Color_Specular;
3790 CGparameter fp_Color_Glow;
3791 CGparameter fp_Color_Pants;
3792 CGparameter fp_Color_Shirt;
3793 CGparameter fp_DeferredColor_Ambient;
3794 CGparameter fp_DeferredColor_Diffuse;
3795 CGparameter fp_DeferredColor_Specular;
3796 CGparameter fp_DeferredMod_Diffuse;
3797 CGparameter fp_DeferredMod_Specular;
3798 CGparameter fp_DistortScaleRefractReflect;
3799 CGparameter fp_EyePosition;
3800 CGparameter fp_FogColor;
3801 CGparameter fp_FogHeightFade;
3802 CGparameter fp_FogPlane;
3803 CGparameter fp_FogPlaneViewDist;
3804 CGparameter fp_FogRangeRecip;
3805 CGparameter fp_LightColor;
3806 CGparameter fp_LightDir;
3807 CGparameter fp_LightPosition;
3808 CGparameter fp_OffsetMapping_Scale;
3809 CGparameter fp_PixelSize;
3810 CGparameter fp_ReflectColor;
3811 CGparameter fp_ReflectFactor;
3812 CGparameter fp_ReflectOffset;
3813 CGparameter fp_RefractColor;
3814 CGparameter fp_Saturation;
3815 CGparameter fp_ScreenCenterRefractReflect;
3816 CGparameter fp_ScreenScaleRefractReflect;
3817 CGparameter fp_ScreenToDepth;
3818 CGparameter fp_ShadowMap_Parameters;
3819 CGparameter fp_ShadowMap_TextureScale;
3820 CGparameter fp_SpecularPower;
3821 CGparameter fp_UserVec1;
3822 CGparameter fp_UserVec2;
3823 CGparameter fp_UserVec3;
3824 CGparameter fp_UserVec4;
3825 CGparameter fp_ViewTintColor;
3826 CGparameter fp_ViewToLight;
3827 CGparameter fp_PixelToScreenTexCoord;
3828 CGparameter fp_ModelToReflectCube;
3832 /// information about each possible shader permutation
3833 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3834 /// currently selected permutation
3835 r_cg_permutation_t *r_cg_permutation;
3836 /// storage for permutations linked in the hash table
3837 memexpandablearray_t r_cg_permutationarray;
3839 #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));}}
3841 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3843 //unsigned int hashdepth = 0;
3844 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3845 r_cg_permutation_t *p;
3846 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3848 if (p->mode == mode && p->permutation == permutation)
3850 //if (hashdepth > 10)
3851 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3856 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3858 p->permutation = permutation;
3859 p->hashnext = r_cg_permutationhash[mode][hashindex];
3860 r_cg_permutationhash[mode][hashindex] = p;
3861 //if (hashdepth > 10)
3862 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3866 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3869 if (!filename || !filename[0])
3871 if (!strcmp(filename, "cg/default.cg"))
3873 if (!cgshaderstring)
3875 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3877 Con_DPrintf("Loading shaders from file %s...\n", filename);
3879 cgshaderstring = (char *)builtincgshaderstring;
3881 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3882 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3883 return shaderstring;
3885 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3888 if (printfromdisknotice)
3889 Con_DPrintf("from disk %s... ", filename);
3890 return shaderstring;
3892 return shaderstring;
3895 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3897 // TODO: load or create .fp and .vp shader files
3900 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3903 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3904 int vertstrings_count = 0, vertstring_length = 0;
3905 int geomstrings_count = 0, geomstring_length = 0;
3906 int fragstrings_count = 0, fragstring_length = 0;
3908 char *vertexstring, *geometrystring, *fragmentstring;
3909 char *vertstring, *geomstring, *fragstring;
3910 const char *vertstrings_list[32+3];
3911 const char *geomstrings_list[32+3];
3912 const char *fragstrings_list[32+3];
3913 char permutationname[256];
3914 char cachename[256];
3915 CGprofile vertexProfile;
3916 CGprofile fragmentProfile;
3924 permutationname[0] = 0;
3926 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
3927 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3928 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3930 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3931 strlcat(cachename, "cg/", sizeof(cachename));
3933 // the first pretext is which type of shader to compile as
3934 // (later these will all be bound together as a program object)
3935 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3936 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3937 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3939 // the second pretext is the mode (for example a light source)
3940 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3941 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3942 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3943 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3944 strlcat(cachename, modeinfo->name, sizeof(cachename));
3946 // now add all the permutation pretexts
3947 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3949 if (permutation & (1<<i))
3951 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3952 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3953 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3954 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3955 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
3959 // keep line numbers correct
3960 vertstrings_list[vertstrings_count++] = "\n";
3961 geomstrings_list[geomstrings_count++] = "\n";
3962 fragstrings_list[fragstrings_count++] = "\n";
3966 // replace spaces in the cachename with _ characters
3967 for (i = 0;cachename[i];i++)
3968 if (cachename[i] == ' ')
3971 // now append the shader text itself
3972 vertstrings_list[vertstrings_count++] = vertexstring;
3973 geomstrings_list[geomstrings_count++] = geometrystring;
3974 fragstrings_list[fragstrings_count++] = fragmentstring;
3976 // if any sources were NULL, clear the respective list
3978 vertstrings_count = 0;
3979 if (!geometrystring)
3980 geomstrings_count = 0;
3981 if (!fragmentstring)
3982 fragstrings_count = 0;
3984 vertstring_length = 0;
3985 for (i = 0;i < vertstrings_count;i++)
3986 vertstring_length += strlen(vertstrings_list[i]);
3987 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3988 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3989 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3991 geomstring_length = 0;
3992 for (i = 0;i < geomstrings_count;i++)
3993 geomstring_length += strlen(geomstrings_list[i]);
3994 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3995 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3996 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3998 fragstring_length = 0;
3999 for (i = 0;i < fragstrings_count;i++)
4000 fragstring_length += strlen(fragstrings_list[i]);
4001 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4002 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4003 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4007 //vertexProfile = CG_PROFILE_ARBVP1;
4008 //fragmentProfile = CG_PROFILE_ARBFP1;
4009 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4010 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4011 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4012 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4013 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4016 // try to load the cached shader, or generate one
4017 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4019 // if caching failed, do a dynamic compile for now
4021 if (vertstring[0] && !p->vprogram)
4022 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4024 if (fragstring[0] && !p->fprogram)
4025 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4028 // look up all the uniform variable names we care about, so we don't
4029 // have to look them up every time we set them
4033 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4034 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4035 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4036 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4037 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4038 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4039 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4040 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4041 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4042 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4043 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4049 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4050 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4051 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4052 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4053 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4054 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4055 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4056 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4057 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4058 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4059 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4060 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4061 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4062 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4063 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4064 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4065 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4066 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4067 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4068 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4069 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4070 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4071 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4072 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4073 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4074 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4075 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4076 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4077 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4078 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4079 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4080 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4081 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4082 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4083 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4084 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4085 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4086 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4087 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4088 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4089 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4090 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4091 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4092 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4093 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4094 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4095 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4096 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4097 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4098 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4099 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4100 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4101 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4102 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4103 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4104 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4105 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4106 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4107 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4108 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4109 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4110 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4111 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4112 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4113 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4114 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4115 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4116 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4117 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4118 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4119 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4120 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4121 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4122 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4123 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4124 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4125 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4129 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4130 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4132 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4136 Mem_Free(vertstring);
4138 Mem_Free(geomstring);
4140 Mem_Free(fragstring);
4142 Mem_Free(vertexstring);
4144 Mem_Free(geometrystring);
4146 Mem_Free(fragmentstring);
4149 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4151 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4154 if (r_cg_permutation != perm)
4156 r_cg_permutation = perm;
4157 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4159 if (!r_cg_permutation->compiled)
4160 R_CG_CompilePermutation(perm, mode, permutation);
4161 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4163 // remove features until we find a valid permutation
4165 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4167 // reduce i more quickly whenever it would not remove any bits
4168 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4169 if (!(permutation & j))
4172 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4173 if (!r_cg_permutation->compiled)
4174 R_CG_CompilePermutation(perm, mode, permutation);
4175 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4178 if (i >= SHADERPERMUTATION_COUNT)
4180 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4181 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4182 return; // no bit left to clear, entire mode is broken
4188 if (r_cg_permutation->vprogram)
4190 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4191 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4192 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4196 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4197 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4199 if (r_cg_permutation->fprogram)
4201 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4202 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4203 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4207 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4208 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4212 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4213 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4214 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4217 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4219 cgGLSetTextureParameter(param, R_GetTexture(tex));
4220 cgGLEnableTextureParameter(param);
4224 void R_GLSL_Restart_f(void)
4226 unsigned int i, limit;
4227 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4228 Mem_Free(glslshaderstring);
4229 glslshaderstring = NULL;
4230 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4231 Mem_Free(cgshaderstring);
4232 cgshaderstring = NULL;
4233 switch(vid.renderpath)
4235 case RENDERPATH_GL20:
4237 r_glsl_permutation_t *p;
4238 r_glsl_permutation = NULL;
4239 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4240 for (i = 0;i < limit;i++)
4242 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4244 GL_Backend_FreeProgram(p->program);
4245 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4248 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4251 case RENDERPATH_CGGL:
4254 r_cg_permutation_t *p;
4255 r_cg_permutation = NULL;
4256 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4257 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4258 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4259 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4260 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4261 for (i = 0;i < limit;i++)
4263 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4266 cgDestroyProgram(p->vprogram);
4268 cgDestroyProgram(p->fprogram);
4269 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4272 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4276 case RENDERPATH_GL13:
4277 case RENDERPATH_GL11:
4282 void R_GLSL_DumpShader_f(void)
4287 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4290 FS_Print(file, "/* The engine may define the following macros:\n");
4291 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4292 for (i = 0;i < SHADERMODE_COUNT;i++)
4293 FS_Print(file, glslshadermodeinfo[i].pretext);
4294 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4295 FS_Print(file, shaderpermutationinfo[i].pretext);
4296 FS_Print(file, "*/\n");
4297 FS_Print(file, builtinshaderstring);
4299 Con_Printf("glsl/default.glsl written\n");
4302 Con_Printf("failed to write to glsl/default.glsl\n");
4305 file = FS_OpenRealFile("cg/default.cg", "w", false);
4308 FS_Print(file, "/* The engine may define the following macros:\n");
4309 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4310 for (i = 0;i < SHADERMODE_COUNT;i++)
4311 FS_Print(file, cgshadermodeinfo[i].pretext);
4312 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4313 FS_Print(file, shaderpermutationinfo[i].pretext);
4314 FS_Print(file, "*/\n");
4315 FS_Print(file, builtincgshaderstring);
4317 Con_Printf("cg/default.cg written\n");
4320 Con_Printf("failed to write to cg/default.cg\n");
4324 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4327 texturemode = GL_MODULATE;
4328 switch (vid.renderpath)
4330 case RENDERPATH_GL20:
4331 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))));
4332 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4333 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4335 case RENDERPATH_CGGL:
4338 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))));
4339 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4340 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4343 case RENDERPATH_GL13:
4344 R_Mesh_TexBind(0, first );
4345 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4346 R_Mesh_TexBind(1, second);
4348 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4350 case RENDERPATH_GL11:
4351 R_Mesh_TexBind(0, first );
4356 void R_SetupShader_DepthOrShadow(void)
4358 switch (vid.renderpath)
4360 case RENDERPATH_GL20:
4361 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4363 case RENDERPATH_CGGL:
4365 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4368 case RENDERPATH_GL13:
4369 R_Mesh_TexBind(0, 0);
4370 R_Mesh_TexBind(1, 0);
4372 case RENDERPATH_GL11:
4373 R_Mesh_TexBind(0, 0);
4378 void R_SetupShader_ShowDepth(void)
4380 switch (vid.renderpath)
4382 case RENDERPATH_GL20:
4383 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4385 case RENDERPATH_CGGL:
4387 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4390 case RENDERPATH_GL13:
4392 case RENDERPATH_GL11:
4397 extern qboolean r_shadow_usingdeferredprepass;
4398 extern cvar_t r_shadow_deferred_8bitrange;
4399 extern rtexture_t *r_shadow_attenuationgradienttexture;
4400 extern rtexture_t *r_shadow_attenuation2dtexture;
4401 extern rtexture_t *r_shadow_attenuation3dtexture;
4402 extern qboolean r_shadow_usingshadowmaprect;
4403 extern qboolean r_shadow_usingshadowmapcube;
4404 extern qboolean r_shadow_usingshadowmap2d;
4405 extern float r_shadow_shadowmap_texturescale[2];
4406 extern float r_shadow_shadowmap_parameters[4];
4407 extern qboolean r_shadow_shadowmapvsdct;
4408 extern qboolean r_shadow_shadowmapsampler;
4409 extern int r_shadow_shadowmappcf;
4410 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4411 extern rtexture_t *r_shadow_shadowmap2dtexture;
4412 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4413 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4414 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4415 extern int r_shadow_prepass_width;
4416 extern int r_shadow_prepass_height;
4417 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4418 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4419 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4420 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4421 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4423 // select a permutation of the lighting shader appropriate to this
4424 // combination of texture, entity, light source, and fogging, only use the
4425 // minimum features necessary to avoid wasting rendering time in the
4426 // fragment shader on features that are not being used
4427 unsigned int permutation = 0;
4428 unsigned int mode = 0;
4430 if (rsurfacepass == RSURFPASS_BACKGROUND)
4432 // distorted background
4433 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4434 mode = SHADERMODE_WATER;
4436 mode = SHADERMODE_REFRACTION;
4437 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4438 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4439 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4440 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4441 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4442 R_Mesh_ColorPointer(NULL, 0, 0);
4443 GL_AlphaTest(false);
4444 GL_BlendFunc(GL_ONE, GL_ZERO);
4446 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4448 if (r_glsl_offsetmapping.integer)
4450 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4451 if (r_glsl_offsetmapping_reliefmapping.integer)
4452 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4454 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4455 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4456 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4457 permutation |= SHADERPERMUTATION_ALPHAKILL;
4458 // normalmap (deferred prepass), may use alpha test on diffuse
4459 mode = SHADERMODE_DEFERREDGEOMETRY;
4460 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4461 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4462 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4463 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4464 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4465 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4466 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4467 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4468 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4470 R_Mesh_ColorPointer(NULL, 0, 0);
4471 GL_AlphaTest(false);
4472 GL_BlendFunc(GL_ONE, GL_ZERO);
4474 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4476 if (r_glsl_offsetmapping.integer)
4478 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4479 if (r_glsl_offsetmapping_reliefmapping.integer)
4480 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4482 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4483 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4485 mode = SHADERMODE_LIGHTSOURCE;
4486 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4487 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4488 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4489 permutation |= SHADERPERMUTATION_CUBEFILTER;
4490 if (diffusescale > 0)
4491 permutation |= SHADERPERMUTATION_DIFFUSE;
4492 if (specularscale > 0)
4494 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4495 if (r_shadow_glossexact.integer)
4496 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4498 if (r_refdef.fogenabled)
4499 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4500 if (rsurface.texture->colormapping)
4501 permutation |= SHADERPERMUTATION_COLORMAPPING;
4502 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4504 if (r_shadow_usingshadowmaprect)
4505 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4506 if (r_shadow_usingshadowmap2d)
4507 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4508 if (r_shadow_usingshadowmapcube)
4509 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4510 else if(r_shadow_shadowmapvsdct)
4511 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4513 if (r_shadow_shadowmapsampler)
4514 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4515 if (r_shadow_shadowmappcf > 1)
4516 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4517 else if (r_shadow_shadowmappcf)
4518 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4520 if (rsurface.texture->reflectmasktexture)
4521 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4522 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4523 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4525 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4526 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4527 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4531 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4532 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4533 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4535 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4536 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4537 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4539 R_Mesh_ColorPointer(NULL, 0, 0);
4540 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4541 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4543 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4545 if (r_glsl_offsetmapping.integer)
4547 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4548 if (r_glsl_offsetmapping_reliefmapping.integer)
4549 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4551 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4552 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4553 // unshaded geometry (fullbright or ambient model lighting)
4554 mode = SHADERMODE_FLATCOLOR;
4555 ambientscale = diffusescale = specularscale = 0;
4556 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4557 permutation |= SHADERPERMUTATION_GLOW;
4558 if (r_refdef.fogenabled)
4559 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4560 if (rsurface.texture->colormapping)
4561 permutation |= SHADERPERMUTATION_COLORMAPPING;
4562 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4563 permutation |= SHADERPERMUTATION_REFLECTION;
4564 if (rsurface.texture->reflectmasktexture)
4565 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4566 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4567 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4569 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4570 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4571 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4575 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4576 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4577 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4579 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4580 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4581 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4583 R_Mesh_ColorPointer(NULL, 0, 0);
4584 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4585 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4587 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4589 if (r_glsl_offsetmapping.integer)
4591 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4592 if (r_glsl_offsetmapping_reliefmapping.integer)
4593 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4595 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4596 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4597 // directional model lighting
4598 mode = SHADERMODE_LIGHTDIRECTION;
4599 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4600 permutation |= SHADERPERMUTATION_GLOW;
4601 permutation |= SHADERPERMUTATION_DIFFUSE;
4602 if (specularscale > 0)
4604 permutation |= SHADERPERMUTATION_SPECULAR;
4605 if (r_shadow_glossexact.integer)
4606 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4608 if (r_refdef.fogenabled)
4609 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4610 if (rsurface.texture->colormapping)
4611 permutation |= SHADERPERMUTATION_COLORMAPPING;
4612 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4613 permutation |= SHADERPERMUTATION_REFLECTION;
4614 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4615 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4616 if (rsurface.texture->reflectmasktexture)
4617 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4618 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4619 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4621 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4622 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4623 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4627 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4628 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4629 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4631 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4632 R_Mesh_ColorPointer(NULL, 0, 0);
4633 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4634 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4636 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4638 if (r_glsl_offsetmapping.integer)
4640 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4641 if (r_glsl_offsetmapping_reliefmapping.integer)
4642 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4644 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4645 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4646 // ambient model lighting
4647 mode = SHADERMODE_LIGHTDIRECTION;
4648 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4649 permutation |= SHADERPERMUTATION_GLOW;
4650 if (r_refdef.fogenabled)
4651 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4652 if (rsurface.texture->colormapping)
4653 permutation |= SHADERPERMUTATION_COLORMAPPING;
4654 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4655 permutation |= SHADERPERMUTATION_REFLECTION;
4656 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4657 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4658 if (rsurface.texture->reflectmasktexture)
4659 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4660 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4661 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4663 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4664 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4665 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4669 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4670 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4671 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4673 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4674 R_Mesh_ColorPointer(NULL, 0, 0);
4675 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4676 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4680 if (r_glsl_offsetmapping.integer)
4682 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4683 if (r_glsl_offsetmapping_reliefmapping.integer)
4684 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4686 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4687 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4689 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4690 permutation |= SHADERPERMUTATION_GLOW;
4691 if (r_refdef.fogenabled)
4692 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4693 if (rsurface.texture->colormapping)
4694 permutation |= SHADERPERMUTATION_COLORMAPPING;
4695 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4696 permutation |= SHADERPERMUTATION_REFLECTION;
4697 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4698 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4699 if (rsurface.texture->reflectmasktexture)
4700 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4701 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4703 // deluxemapping (light direction texture)
4704 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4705 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4707 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4708 permutation |= SHADERPERMUTATION_DIFFUSE;
4709 if (specularscale > 0)
4711 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4712 if (r_shadow_glossexact.integer)
4713 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4715 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4716 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4717 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4719 R_Mesh_ColorPointer(NULL, 0, 0);
4721 else if (r_glsl_deluxemapping.integer >= 2)
4723 // fake deluxemapping (uniform light direction in tangentspace)
4724 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4725 permutation |= SHADERPERMUTATION_DIFFUSE;
4726 if (specularscale > 0)
4728 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4729 if (r_shadow_glossexact.integer)
4730 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4732 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4733 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4734 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4736 R_Mesh_ColorPointer(NULL, 0, 0);
4738 else if (rsurface.uselightmaptexture)
4740 // ordinary lightmapping (q1bsp, q3bsp)
4741 mode = SHADERMODE_LIGHTMAP;
4742 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4743 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4744 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4746 R_Mesh_ColorPointer(NULL, 0, 0);
4750 // ordinary vertex coloring (q3bsp)
4751 mode = SHADERMODE_VERTEXCOLOR;
4752 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4753 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4755 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4756 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4758 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4759 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4760 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4764 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4765 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4766 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4768 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4769 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4771 switch(vid.renderpath)
4773 case RENDERPATH_GL20:
4774 R_SetupShader_SetPermutationGLSL(mode, permutation);
4775 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4776 if (mode == SHADERMODE_LIGHTSOURCE)
4778 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4779 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4780 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4781 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);
4782 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);
4783 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);
4785 // additive passes are only darkened by fog, not tinted
4786 if (r_glsl_permutation->loc_FogColor >= 0)
4787 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4788 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]);
4789 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]);
4790 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4794 if (mode == SHADERMODE_FLATCOLOR)
4796 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4798 else if (mode == SHADERMODE_LIGHTDIRECTION)
4800 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]);
4801 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]);
4802 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);
4803 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);
4804 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);
4805 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]);
4806 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]);
4810 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]);
4811 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]);
4812 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);
4813 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);
4814 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);
4816 // additive passes are only darkened by fog, not tinted
4817 if (r_glsl_permutation->loc_FogColor >= 0)
4819 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4820 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4822 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4824 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);
4825 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]);
4826 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]);
4827 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4828 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4829 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4830 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4831 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4833 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4834 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4835 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4836 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4837 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4838 if (r_glsl_permutation->loc_Color_Pants >= 0)
4840 if (rsurface.texture->pantstexture)
4841 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4843 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4845 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4847 if (rsurface.texture->shirttexture)
4848 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4850 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4852 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]);
4853 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4854 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4855 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4856 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4857 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]);
4858 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4860 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
4861 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
4862 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
4863 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
4864 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
4865 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
4866 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
4867 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
4868 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
4869 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
4870 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
4871 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
4872 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
4873 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
4874 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
4875 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
4876 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
4877 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap );
4878 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
4879 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white );
4880 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white );
4881 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
4882 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
4883 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
4884 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
4885 if (rsurface.rtlight)
4887 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
4888 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
4889 if (r_shadow_usingshadowmapcube)
4890 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4891 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
4892 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
4896 case RENDERPATH_CGGL:
4898 R_SetupShader_SetPermutationCG(mode, permutation);
4899 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
4900 if (mode == SHADERMODE_LIGHTSOURCE)
4902 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4903 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4907 if (mode == SHADERMODE_LIGHTDIRECTION)
4909 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
4912 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4913 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4914 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4915 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
4918 if (mode == SHADERMODE_LIGHTSOURCE)
4920 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4921 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4922 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
4923 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
4924 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
4926 // additive passes are only darkened by fog, not tinted
4927 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4928 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
4929 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
4930 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4934 if (mode == SHADERMODE_FLATCOLOR)
4936 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4938 else if (mode == SHADERMODE_LIGHTDIRECTION)
4940 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
4941 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
4942 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
4943 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
4944 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
4945 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
4946 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
4950 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
4951 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
4952 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
4953 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
4954 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
4956 // additive passes are only darkened by fog, not tinted
4957 if (r_cg_permutation->fp_FogColor)
4959 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4960 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4962 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4965 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
4966 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
4967 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
4968 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4969 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4970 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4971 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4972 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4974 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4975 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4976 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4977 if (r_cg_permutation->fp_Color_Pants)
4979 if (rsurface.texture->pantstexture)
4980 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4982 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4985 if (r_cg_permutation->fp_Color_Shirt)
4987 if (rsurface.texture->shirttexture)
4988 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4990 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4993 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
4994 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4995 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4996 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4997 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4998 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
4999 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5001 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
5002 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
5003 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
5004 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
5005 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
5006 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
5007 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
5008 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
5009 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
5010 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
5011 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
5012 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
5013 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
5014 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
5015 if (r_cg_permutation->fp_Texture_ReflectCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
5016 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
5017 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
5018 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
5019 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5020 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , r_texture_white );CHECKCGERROR
5021 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , r_texture_white );CHECKCGERROR
5022 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5023 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5024 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
5025 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
5026 if (rsurface.rtlight)
5028 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5029 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5030 if (r_shadow_usingshadowmapcube)
5031 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5032 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5033 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5039 case RENDERPATH_GL13:
5040 case RENDERPATH_GL11:
5045 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5047 // select a permutation of the lighting shader appropriate to this
5048 // combination of texture, entity, light source, and fogging, only use the
5049 // minimum features necessary to avoid wasting rendering time in the
5050 // fragment shader on features that are not being used
5051 unsigned int permutation = 0;
5052 unsigned int mode = 0;
5053 const float *lightcolorbase = rtlight->currentcolor;
5054 float ambientscale = rtlight->ambientscale;
5055 float diffusescale = rtlight->diffusescale;
5056 float specularscale = rtlight->specularscale;
5057 // this is the location of the light in view space
5058 vec3_t viewlightorigin;
5059 // this transforms from view space (camera) to light space (cubemap)
5060 matrix4x4_t viewtolight;
5061 matrix4x4_t lighttoview;
5062 float viewtolight16f[16];
5063 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5065 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5066 if (rtlight->currentcubemap != r_texture_whitecube)
5067 permutation |= SHADERPERMUTATION_CUBEFILTER;
5068 if (diffusescale > 0)
5069 permutation |= SHADERPERMUTATION_DIFFUSE;
5070 if (specularscale > 0)
5072 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5073 if (r_shadow_glossexact.integer)
5074 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5076 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5078 if (r_shadow_usingshadowmaprect)
5079 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5080 if (r_shadow_usingshadowmap2d)
5081 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5082 if (r_shadow_usingshadowmapcube)
5083 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5084 else if(r_shadow_shadowmapvsdct)
5085 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5087 if (r_shadow_shadowmapsampler)
5088 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5089 if (r_shadow_shadowmappcf > 1)
5090 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5091 else if (r_shadow_shadowmappcf)
5092 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5094 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5095 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5096 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5097 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5098 switch(vid.renderpath)
5100 case RENDERPATH_GL20:
5101 R_SetupShader_SetPermutationGLSL(mode, permutation);
5102 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5103 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5104 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);
5105 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);
5106 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);
5107 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]);
5108 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]);
5109 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));
5110 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]);
5111 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5113 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5114 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5115 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5116 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5117 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
5118 if (r_shadow_usingshadowmapcube)
5119 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5120 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5121 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5123 case RENDERPATH_CGGL:
5125 R_SetupShader_SetPermutationCG(mode, permutation);
5126 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5127 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5128 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
5129 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
5130 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
5131 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
5132 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
5133 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
5134 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
5135 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5137 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5138 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5139 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5140 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5141 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5142 if (r_shadow_usingshadowmapcube)
5143 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5144 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5145 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5148 case RENDERPATH_GL13:
5149 case RENDERPATH_GL11:
5154 #define SKINFRAME_HASH 1024
5158 int loadsequence; // incremented each level change
5159 memexpandablearray_t array;
5160 skinframe_t *hash[SKINFRAME_HASH];
5163 r_skinframe_t r_skinframe;
5165 void R_SkinFrame_PrepareForPurge(void)
5167 r_skinframe.loadsequence++;
5168 // wrap it without hitting zero
5169 if (r_skinframe.loadsequence >= 200)
5170 r_skinframe.loadsequence = 1;
5173 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5177 // mark the skinframe as used for the purging code
5178 skinframe->loadsequence = r_skinframe.loadsequence;
5181 void R_SkinFrame_Purge(void)
5185 for (i = 0;i < SKINFRAME_HASH;i++)
5187 for (s = r_skinframe.hash[i];s;s = s->next)
5189 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5191 if (s->merged == s->base)
5193 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5194 R_PurgeTexture(s->stain );s->stain = NULL;
5195 R_PurgeTexture(s->merged);s->merged = NULL;
5196 R_PurgeTexture(s->base );s->base = NULL;
5197 R_PurgeTexture(s->pants );s->pants = NULL;
5198 R_PurgeTexture(s->shirt );s->shirt = NULL;
5199 R_PurgeTexture(s->nmap );s->nmap = NULL;
5200 R_PurgeTexture(s->gloss );s->gloss = NULL;
5201 R_PurgeTexture(s->glow );s->glow = NULL;
5202 R_PurgeTexture(s->fog );s->fog = NULL;
5203 R_PurgeTexture(s->reflect);s->reflect = NULL;
5204 s->loadsequence = 0;
5210 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5212 char basename[MAX_QPATH];
5214 Image_StripImageExtension(name, basename, sizeof(basename));
5216 if( last == NULL ) {
5218 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5219 item = r_skinframe.hash[hashindex];
5224 // linearly search through the hash bucket
5225 for( ; item ; item = item->next ) {
5226 if( !strcmp( item->basename, basename ) ) {
5233 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5237 char basename[MAX_QPATH];
5239 Image_StripImageExtension(name, basename, sizeof(basename));
5241 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5242 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5243 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5247 rtexture_t *dyntexture;
5248 // check whether its a dynamic texture
5249 dyntexture = CL_GetDynTexture( basename );
5250 if (!add && !dyntexture)
5252 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5253 memset(item, 0, sizeof(*item));
5254 strlcpy(item->basename, basename, sizeof(item->basename));
5255 item->base = dyntexture; // either NULL or dyntexture handle
5256 item->textureflags = textureflags;
5257 item->comparewidth = comparewidth;
5258 item->compareheight = compareheight;
5259 item->comparecrc = comparecrc;
5260 item->next = r_skinframe.hash[hashindex];
5261 r_skinframe.hash[hashindex] = item;
5263 else if( item->base == NULL )
5265 rtexture_t *dyntexture;
5266 // check whether its a dynamic texture
5267 // 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]
5268 dyntexture = CL_GetDynTexture( basename );
5269 item->base = dyntexture; // either NULL or dyntexture handle
5272 R_SkinFrame_MarkUsed(item);
5276 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5278 unsigned long long avgcolor[5], wsum; \
5286 for(pix = 0; pix < cnt; ++pix) \
5289 for(comp = 0; comp < 3; ++comp) \
5291 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5294 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5296 for(comp = 0; comp < 3; ++comp) \
5297 avgcolor[comp] += getpixel * w; \
5300 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5301 avgcolor[4] += getpixel; \
5303 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5305 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5306 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5307 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5308 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5311 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5314 unsigned char *pixels;
5315 unsigned char *bumppixels;
5316 unsigned char *basepixels = NULL;
5317 int basepixels_width = 0;
5318 int basepixels_height = 0;
5319 skinframe_t *skinframe;
5320 rtexture_t *ddsbase = NULL;
5321 qboolean ddshasalpha = false;
5322 float ddsavgcolor[4];
5323 char basename[MAX_QPATH];
5325 if (cls.state == ca_dedicated)
5328 // return an existing skinframe if already loaded
5329 // if loading of the first image fails, don't make a new skinframe as it
5330 // would cause all future lookups of this to be missing
5331 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5332 if (skinframe && skinframe->base)
5335 Image_StripImageExtension(name, basename, sizeof(basename));
5337 // check for DDS texture file first
5338 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5340 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5341 if (basepixels == NULL)
5345 if (developer_loading.integer)
5346 Con_Printf("loading skin \"%s\"\n", name);
5348 // we've got some pixels to store, so really allocate this new texture now
5350 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5351 skinframe->stain = NULL;
5352 skinframe->merged = NULL;
5353 skinframe->base = NULL;
5354 skinframe->pants = NULL;
5355 skinframe->shirt = NULL;
5356 skinframe->nmap = NULL;
5357 skinframe->gloss = NULL;
5358 skinframe->glow = NULL;
5359 skinframe->fog = NULL;
5360 skinframe->reflect = NULL;
5361 skinframe->hasalpha = false;
5365 skinframe->base = ddsbase;
5366 skinframe->hasalpha = ddshasalpha;
5367 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5368 if (r_loadfog && skinframe->hasalpha)
5369 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5370 //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]);
5374 basepixels_width = image_width;
5375 basepixels_height = image_height;
5376 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);
5377 if (textureflags & TEXF_ALPHA)
5379 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5381 if (basepixels[j] < 255)
5383 skinframe->hasalpha = true;
5387 if (r_loadfog && skinframe->hasalpha)
5389 // has transparent pixels
5390 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5391 for (j = 0;j < image_width * image_height * 4;j += 4)
5396 pixels[j+3] = basepixels[j+3];
5398 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);
5402 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5403 //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]);
5404 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5405 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5406 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5407 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5412 if (r_loadnormalmap)
5413 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5414 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5416 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5417 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5418 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5419 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5422 // _norm is the name used by tenebrae and has been adopted as standard
5423 if (r_loadnormalmap && skinframe->nmap == NULL)
5425 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5427 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);
5431 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5433 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5434 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5435 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);
5437 Mem_Free(bumppixels);
5439 else if (r_shadow_bumpscale_basetexture.value > 0)
5441 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5442 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5443 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);
5446 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5447 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5450 // _luma is supported only for tenebrae compatibility
5451 // _glow is the preferred name
5452 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))))
5454 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);
5455 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5456 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5457 Mem_Free(pixels);pixels = NULL;
5460 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5462 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);
5463 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5464 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5469 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5471 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);
5472 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5473 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5478 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5480 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);
5481 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5482 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5487 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5489 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5490 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5491 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5497 Mem_Free(basepixels);
5502 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5503 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5506 unsigned char *temp1, *temp2;
5507 skinframe_t *skinframe;
5509 if (cls.state == ca_dedicated)
5512 // if already loaded just return it, otherwise make a new skinframe
5513 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5514 if (skinframe && skinframe->base)
5517 skinframe->stain = NULL;
5518 skinframe->merged = NULL;
5519 skinframe->base = NULL;
5520 skinframe->pants = NULL;
5521 skinframe->shirt = NULL;
5522 skinframe->nmap = NULL;
5523 skinframe->gloss = NULL;
5524 skinframe->glow = NULL;
5525 skinframe->fog = NULL;
5526 skinframe->reflect = NULL;
5527 skinframe->hasalpha = false;
5529 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5533 if (developer_loading.integer)
5534 Con_Printf("loading 32bit skin \"%s\"\n", name);
5536 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5538 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5539 temp2 = temp1 + width * height * 4;
5540 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5541 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5544 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5545 if (textureflags & TEXF_ALPHA)
5547 for (i = 3;i < width * height * 4;i += 4)
5549 if (skindata[i] < 255)
5551 skinframe->hasalpha = true;
5555 if (r_loadfog && skinframe->hasalpha)
5557 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5558 memcpy(fogpixels, skindata, width * height * 4);
5559 for (i = 0;i < width * height * 4;i += 4)
5560 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5561 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5562 Mem_Free(fogpixels);
5566 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5567 //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]);
5572 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5576 skinframe_t *skinframe;
5578 if (cls.state == ca_dedicated)
5581 // if already loaded just return it, otherwise make a new skinframe
5582 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5583 if (skinframe && skinframe->base)
5586 skinframe->stain = NULL;
5587 skinframe->merged = NULL;
5588 skinframe->base = NULL;
5589 skinframe->pants = NULL;
5590 skinframe->shirt = NULL;
5591 skinframe->nmap = NULL;
5592 skinframe->gloss = NULL;
5593 skinframe->glow = NULL;
5594 skinframe->fog = NULL;
5595 skinframe->reflect = NULL;
5596 skinframe->hasalpha = false;
5598 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5602 if (developer_loading.integer)
5603 Con_Printf("loading quake skin \"%s\"\n", name);
5605 // 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)
5606 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5607 memcpy(skinframe->qpixels, skindata, width*height);
5608 skinframe->qwidth = width;
5609 skinframe->qheight = height;
5612 for (i = 0;i < width * height;i++)
5613 featuresmask |= palette_featureflags[skindata[i]];
5615 skinframe->hasalpha = false;
5616 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5617 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5618 skinframe->qgeneratemerged = true;
5619 skinframe->qgeneratebase = skinframe->qhascolormapping;
5620 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5622 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5623 //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]);
5628 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5632 unsigned char *skindata;
5634 if (!skinframe->qpixels)
5637 if (!skinframe->qhascolormapping)
5638 colormapped = false;
5642 if (!skinframe->qgeneratebase)
5647 if (!skinframe->qgeneratemerged)
5651 width = skinframe->qwidth;
5652 height = skinframe->qheight;
5653 skindata = skinframe->qpixels;
5655 if (skinframe->qgeneratenmap)
5657 unsigned char *temp1, *temp2;
5658 skinframe->qgeneratenmap = false;
5659 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5660 temp2 = temp1 + width * height * 4;
5661 // use either a custom palette or the quake palette
5662 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5663 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5664 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5668 if (skinframe->qgenerateglow)
5670 skinframe->qgenerateglow = false;
5671 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5676 skinframe->qgeneratebase = false;
5677 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);
5678 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5679 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5683 skinframe->qgeneratemerged = false;
5684 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5687 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5689 Mem_Free(skinframe->qpixels);
5690 skinframe->qpixels = NULL;
5694 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)
5697 skinframe_t *skinframe;
5699 if (cls.state == ca_dedicated)
5702 // if already loaded just return it, otherwise make a new skinframe
5703 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5704 if (skinframe && skinframe->base)
5707 skinframe->stain = NULL;
5708 skinframe->merged = NULL;
5709 skinframe->base = NULL;
5710 skinframe->pants = NULL;
5711 skinframe->shirt = NULL;
5712 skinframe->nmap = NULL;
5713 skinframe->gloss = NULL;
5714 skinframe->glow = NULL;
5715 skinframe->fog = NULL;
5716 skinframe->reflect = NULL;
5717 skinframe->hasalpha = false;
5719 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5723 if (developer_loading.integer)
5724 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5726 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5727 if (textureflags & TEXF_ALPHA)
5729 for (i = 0;i < width * height;i++)
5731 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5733 skinframe->hasalpha = true;
5737 if (r_loadfog && skinframe->hasalpha)
5738 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5741 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5742 //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]);
5747 skinframe_t *R_SkinFrame_LoadMissing(void)
5749 skinframe_t *skinframe;
5751 if (cls.state == ca_dedicated)
5754 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5755 skinframe->stain = NULL;
5756 skinframe->merged = NULL;
5757 skinframe->base = NULL;
5758 skinframe->pants = NULL;
5759 skinframe->shirt = NULL;
5760 skinframe->nmap = NULL;
5761 skinframe->gloss = NULL;
5762 skinframe->glow = NULL;
5763 skinframe->fog = NULL;
5764 skinframe->reflect = NULL;
5765 skinframe->hasalpha = false;
5767 skinframe->avgcolor[0] = rand() / RAND_MAX;
5768 skinframe->avgcolor[1] = rand() / RAND_MAX;
5769 skinframe->avgcolor[2] = rand() / RAND_MAX;
5770 skinframe->avgcolor[3] = 1;
5775 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5776 typedef struct suffixinfo_s
5779 qboolean flipx, flipy, flipdiagonal;
5782 static suffixinfo_t suffix[3][6] =
5785 {"px", false, false, false},
5786 {"nx", false, false, false},
5787 {"py", false, false, false},
5788 {"ny", false, false, false},
5789 {"pz", false, false, false},
5790 {"nz", false, false, false}
5793 {"posx", false, false, false},
5794 {"negx", false, false, false},
5795 {"posy", false, false, false},
5796 {"negy", false, false, false},
5797 {"posz", false, false, false},
5798 {"negz", false, false, false}
5801 {"rt", true, false, true},
5802 {"lf", false, true, true},
5803 {"ft", true, true, false},
5804 {"bk", false, false, false},
5805 {"up", true, false, true},
5806 {"dn", true, false, true}
5810 static int componentorder[4] = {0, 1, 2, 3};
5812 rtexture_t *R_LoadCubemap(const char *basename)
5814 int i, j, cubemapsize;
5815 unsigned char *cubemappixels, *image_buffer;
5816 rtexture_t *cubemaptexture;
5818 // must start 0 so the first loadimagepixels has no requested width/height
5820 cubemappixels = NULL;
5821 cubemaptexture = NULL;
5822 // keep trying different suffix groups (posx, px, rt) until one loads
5823 for (j = 0;j < 3 && !cubemappixels;j++)
5825 // load the 6 images in the suffix group
5826 for (i = 0;i < 6;i++)
5828 // generate an image name based on the base and and suffix
5829 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5831 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
5833 // an image loaded, make sure width and height are equal
5834 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
5836 // if this is the first image to load successfully, allocate the cubemap memory
5837 if (!cubemappixels && image_width >= 1)
5839 cubemapsize = image_width;
5840 // note this clears to black, so unavailable sides are black
5841 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
5843 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
5845 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
5848 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
5850 Mem_Free(image_buffer);
5854 // if a cubemap loaded, upload it
5857 if (developer_loading.integer)
5858 Con_Printf("loading cubemap \"%s\"\n", basename);
5860 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
5861 Mem_Free(cubemappixels);
5865 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
5866 if (developer_loading.integer)
5868 Con_Printf("(tried tried images ");
5869 for (j = 0;j < 3;j++)
5870 for (i = 0;i < 6;i++)
5871 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
5872 Con_Print(" and was unable to find any of them).\n");
5875 return cubemaptexture;
5878 rtexture_t *R_GetCubemap(const char *basename)
5881 for (i = 0;i < r_texture_numcubemaps;i++)
5882 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
5883 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
5884 if (i >= MAX_CUBEMAPS)
5885 return r_texture_whitecube;
5886 r_texture_numcubemaps++;
5887 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
5888 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
5889 return r_texture_cubemaps[i].texture;
5892 void R_FreeCubemaps(void)
5895 for (i = 0;i < r_texture_numcubemaps;i++)
5897 if (developer_loading.integer)
5898 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
5899 if (r_texture_cubemaps[i].texture)
5900 R_FreeTexture(r_texture_cubemaps[i].texture);
5902 r_texture_numcubemaps = 0;
5905 void R_Main_FreeViewCache(void)
5907 if (r_refdef.viewcache.entityvisible)
5908 Mem_Free(r_refdef.viewcache.entityvisible);
5909 if (r_refdef.viewcache.world_pvsbits)
5910 Mem_Free(r_refdef.viewcache.world_pvsbits);
5911 if (r_refdef.viewcache.world_leafvisible)
5912 Mem_Free(r_refdef.viewcache.world_leafvisible);
5913 if (r_refdef.viewcache.world_surfacevisible)
5914 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5915 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5918 void R_Main_ResizeViewCache(void)
5920 int numentities = r_refdef.scene.numentities;
5921 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5922 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5923 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5924 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5925 if (r_refdef.viewcache.maxentities < numentities)
5927 r_refdef.viewcache.maxentities = numentities;
5928 if (r_refdef.viewcache.entityvisible)
5929 Mem_Free(r_refdef.viewcache.entityvisible);
5930 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5932 if (r_refdef.viewcache.world_numclusters != numclusters)
5934 r_refdef.viewcache.world_numclusters = numclusters;
5935 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5936 if (r_refdef.viewcache.world_pvsbits)
5937 Mem_Free(r_refdef.viewcache.world_pvsbits);
5938 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5940 if (r_refdef.viewcache.world_numleafs != numleafs)
5942 r_refdef.viewcache.world_numleafs = numleafs;
5943 if (r_refdef.viewcache.world_leafvisible)
5944 Mem_Free(r_refdef.viewcache.world_leafvisible);
5945 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5947 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5949 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5950 if (r_refdef.viewcache.world_surfacevisible)
5951 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5952 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5956 extern rtexture_t *loadingscreentexture;
5957 void gl_main_start(void)
5959 loadingscreentexture = NULL;
5960 r_texture_blanknormalmap = NULL;
5961 r_texture_white = NULL;
5962 r_texture_grey128 = NULL;
5963 r_texture_black = NULL;
5964 r_texture_whitecube = NULL;
5965 r_texture_normalizationcube = NULL;
5966 r_texture_fogattenuation = NULL;
5967 r_texture_gammaramps = NULL;
5968 r_texture_numcubemaps = 0;
5970 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5971 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5973 switch(vid.renderpath)
5975 case RENDERPATH_GL20:
5976 case RENDERPATH_CGGL:
5977 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5978 Cvar_SetValueQuick(&gl_combine, 1);
5979 Cvar_SetValueQuick(&r_glsl, 1);
5980 r_loadnormalmap = true;
5984 case RENDERPATH_GL13:
5985 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5986 Cvar_SetValueQuick(&gl_combine, 1);
5987 Cvar_SetValueQuick(&r_glsl, 0);
5988 r_loadnormalmap = false;
5989 r_loadgloss = false;
5992 case RENDERPATH_GL11:
5993 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5994 Cvar_SetValueQuick(&gl_combine, 0);
5995 Cvar_SetValueQuick(&r_glsl, 0);
5996 r_loadnormalmap = false;
5997 r_loadgloss = false;
6003 R_FrameData_Reset();
6007 memset(r_queries, 0, sizeof(r_queries));
6009 r_qwskincache = NULL;
6010 r_qwskincache_size = 0;
6012 // set up r_skinframe loading system for textures
6013 memset(&r_skinframe, 0, sizeof(r_skinframe));
6014 r_skinframe.loadsequence = 1;
6015 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6017 r_main_texturepool = R_AllocTexturePool();
6018 R_BuildBlankTextures();
6020 if (vid.support.arb_texture_cube_map)
6023 R_BuildNormalizationCube();
6025 r_texture_fogattenuation = NULL;
6026 r_texture_gammaramps = NULL;
6027 //r_texture_fogintensity = NULL;
6028 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6029 memset(&r_waterstate, 0, sizeof(r_waterstate));
6030 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6031 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6032 glslshaderstring = NULL;
6034 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6035 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6036 cgshaderstring = NULL;
6038 memset(&r_svbsp, 0, sizeof (r_svbsp));
6040 r_refdef.fogmasktable_density = 0;
6043 void gl_main_shutdown(void)
6046 R_FrameData_Reset();
6048 R_Main_FreeViewCache();
6051 qglDeleteQueriesARB(r_maxqueries, r_queries);
6055 memset(r_queries, 0, sizeof(r_queries));
6057 r_qwskincache = NULL;
6058 r_qwskincache_size = 0;
6060 // clear out the r_skinframe state
6061 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6062 memset(&r_skinframe, 0, sizeof(r_skinframe));
6065 Mem_Free(r_svbsp.nodes);
6066 memset(&r_svbsp, 0, sizeof (r_svbsp));
6067 R_FreeTexturePool(&r_main_texturepool);
6068 loadingscreentexture = NULL;
6069 r_texture_blanknormalmap = NULL;
6070 r_texture_white = NULL;
6071 r_texture_grey128 = NULL;
6072 r_texture_black = NULL;
6073 r_texture_whitecube = NULL;
6074 r_texture_normalizationcube = NULL;
6075 r_texture_fogattenuation = NULL;
6076 r_texture_gammaramps = NULL;
6077 r_texture_numcubemaps = 0;
6078 //r_texture_fogintensity = NULL;
6079 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6080 memset(&r_waterstate, 0, sizeof(r_waterstate));
6084 extern void CL_ParseEntityLump(char *entitystring);
6085 void gl_main_newmap(void)
6087 // FIXME: move this code to client
6089 char *entities, entname[MAX_QPATH];
6091 Mem_Free(r_qwskincache);
6092 r_qwskincache = NULL;
6093 r_qwskincache_size = 0;
6096 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6097 l = (int)strlen(entname) - 4;
6098 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6100 memcpy(entname + l, ".ent", 5);
6101 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6103 CL_ParseEntityLump(entities);
6108 if (cl.worldmodel->brush.entities)
6109 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6111 R_Main_FreeViewCache();
6113 R_FrameData_Reset();
6116 void GL_Main_Init(void)
6118 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6120 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6121 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6122 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6123 if (gamemode == GAME_NEHAHRA)
6125 Cvar_RegisterVariable (&gl_fogenable);
6126 Cvar_RegisterVariable (&gl_fogdensity);
6127 Cvar_RegisterVariable (&gl_fogred);
6128 Cvar_RegisterVariable (&gl_foggreen);
6129 Cvar_RegisterVariable (&gl_fogblue);
6130 Cvar_RegisterVariable (&gl_fogstart);
6131 Cvar_RegisterVariable (&gl_fogend);
6132 Cvar_RegisterVariable (&gl_skyclip);
6134 Cvar_RegisterVariable(&r_motionblur);
6135 Cvar_RegisterVariable(&r_motionblur_maxblur);
6136 Cvar_RegisterVariable(&r_motionblur_bmin);
6137 Cvar_RegisterVariable(&r_motionblur_vmin);
6138 Cvar_RegisterVariable(&r_motionblur_vmax);
6139 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6140 Cvar_RegisterVariable(&r_motionblur_randomize);
6141 Cvar_RegisterVariable(&r_damageblur);
6142 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6143 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6144 Cvar_RegisterVariable(&r_equalize_entities_by);
6145 Cvar_RegisterVariable(&r_equalize_entities_to);
6146 Cvar_RegisterVariable(&r_depthfirst);
6147 Cvar_RegisterVariable(&r_useinfinitefarclip);
6148 Cvar_RegisterVariable(&r_farclip_base);
6149 Cvar_RegisterVariable(&r_farclip_world);
6150 Cvar_RegisterVariable(&r_nearclip);
6151 Cvar_RegisterVariable(&r_showbboxes);
6152 Cvar_RegisterVariable(&r_showsurfaces);
6153 Cvar_RegisterVariable(&r_showtris);
6154 Cvar_RegisterVariable(&r_shownormals);
6155 Cvar_RegisterVariable(&r_showlighting);
6156 Cvar_RegisterVariable(&r_showshadowvolumes);
6157 Cvar_RegisterVariable(&r_showcollisionbrushes);
6158 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6159 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6160 Cvar_RegisterVariable(&r_showdisabledepthtest);
6161 Cvar_RegisterVariable(&r_drawportals);
6162 Cvar_RegisterVariable(&r_drawentities);
6163 Cvar_RegisterVariable(&r_cullentities_trace);
6164 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6165 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6166 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6167 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6168 Cvar_RegisterVariable(&r_drawviewmodel);
6169 Cvar_RegisterVariable(&r_speeds);
6170 Cvar_RegisterVariable(&r_fullbrights);
6171 Cvar_RegisterVariable(&r_wateralpha);
6172 Cvar_RegisterVariable(&r_dynamic);
6173 Cvar_RegisterVariable(&r_fullbright);
6174 Cvar_RegisterVariable(&r_shadows);
6175 Cvar_RegisterVariable(&r_shadows_darken);
6176 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6177 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6178 Cvar_RegisterVariable(&r_shadows_throwdistance);
6179 Cvar_RegisterVariable(&r_shadows_throwdirection);
6180 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6181 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6182 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6183 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6184 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6185 Cvar_RegisterVariable(&r_fog_exp2);
6186 Cvar_RegisterVariable(&r_drawfog);
6187 Cvar_RegisterVariable(&r_transparentdepthmasking);
6188 Cvar_RegisterVariable(&r_texture_dds_load);
6189 Cvar_RegisterVariable(&r_texture_dds_save);
6190 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6191 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6192 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6193 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6194 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6195 Cvar_RegisterVariable(&r_textureunits);
6196 Cvar_RegisterVariable(&gl_combine);
6197 Cvar_RegisterVariable(&r_glsl);
6198 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6199 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6200 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6201 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6202 Cvar_RegisterVariable(&r_glsl_postprocess);
6203 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6204 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6205 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6206 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6207 Cvar_RegisterVariable(&r_water);
6208 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6209 Cvar_RegisterVariable(&r_water_clippingplanebias);
6210 Cvar_RegisterVariable(&r_water_refractdistort);
6211 Cvar_RegisterVariable(&r_water_reflectdistort);
6212 Cvar_RegisterVariable(&r_lerpsprites);
6213 Cvar_RegisterVariable(&r_lerpmodels);
6214 Cvar_RegisterVariable(&r_lerplightstyles);
6215 Cvar_RegisterVariable(&r_waterscroll);
6216 Cvar_RegisterVariable(&r_bloom);
6217 Cvar_RegisterVariable(&r_bloom_colorscale);
6218 Cvar_RegisterVariable(&r_bloom_brighten);
6219 Cvar_RegisterVariable(&r_bloom_blur);
6220 Cvar_RegisterVariable(&r_bloom_resolution);
6221 Cvar_RegisterVariable(&r_bloom_colorexponent);
6222 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6223 Cvar_RegisterVariable(&r_hdr);
6224 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6225 Cvar_RegisterVariable(&r_hdr_glowintensity);
6226 Cvar_RegisterVariable(&r_hdr_range);
6227 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6228 Cvar_RegisterVariable(&developer_texturelogging);
6229 Cvar_RegisterVariable(&gl_lightmaps);
6230 Cvar_RegisterVariable(&r_test);
6231 Cvar_RegisterVariable(&r_batchmode);
6232 Cvar_RegisterVariable(&r_glsl_saturation);
6233 Cvar_RegisterVariable(&r_framedatasize);
6234 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6235 Cvar_SetValue("r_fullbrights", 0);
6236 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6238 Cvar_RegisterVariable(&r_track_sprites);
6239 Cvar_RegisterVariable(&r_track_sprites_flags);
6240 Cvar_RegisterVariable(&r_track_sprites_scalew);
6241 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6242 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6243 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6246 extern void R_Textures_Init(void);
6247 extern void GL_Draw_Init(void);
6248 extern void GL_Main_Init(void);
6249 extern void R_Shadow_Init(void);
6250 extern void R_Sky_Init(void);
6251 extern void GL_Surf_Init(void);
6252 extern void R_Particles_Init(void);
6253 extern void R_Explosion_Init(void);
6254 extern void gl_backend_init(void);
6255 extern void Sbar_Init(void);
6256 extern void R_LightningBeams_Init(void);
6257 extern void Mod_RenderInit(void);
6258 extern void Font_Init(void);
6260 void Render_Init(void)
6273 R_LightningBeams_Init();
6282 extern char *ENGINE_EXTENSIONS;
6285 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6286 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6287 gl_version = (const char *)qglGetString(GL_VERSION);
6288 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6292 if (!gl_platformextensions)
6293 gl_platformextensions = "";
6295 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6296 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6297 Con_Printf("GL_VERSION: %s\n", gl_version);
6298 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6299 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6301 VID_CheckExtensions();
6303 // LordHavoc: report supported extensions
6304 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6306 // clear to black (loading plaque will be seen over this)
6308 qglClearColor(0,0,0,1);CHECKGLERROR
6309 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6312 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6316 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6318 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6321 p = r_refdef.view.frustum + i;
6326 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6330 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6334 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6338 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6342 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6346 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6350 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6354 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6362 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6366 for (i = 0;i < numplanes;i++)
6373 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6377 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6381 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6385 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6389 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6393 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6397 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6401 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6409 //==================================================================================
6411 // LordHavoc: this stores temporary data used within the same frame
6413 qboolean r_framedata_failed;
6414 static size_t r_framedata_size;
6415 static size_t r_framedata_current;
6416 static void *r_framedata_base;
6418 void R_FrameData_Reset(void)
6420 if (r_framedata_base)
6421 Mem_Free(r_framedata_base);
6422 r_framedata_base = NULL;
6423 r_framedata_size = 0;
6424 r_framedata_current = 0;
6425 r_framedata_failed = false;
6428 void R_FrameData_NewFrame(void)
6431 if (r_framedata_failed)
6432 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6433 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6434 wantedsize = bound(65536, wantedsize, 128*1024*1024);
6435 if (r_framedata_size != wantedsize)
6437 r_framedata_size = wantedsize;
6438 if (r_framedata_base)
6439 Mem_Free(r_framedata_base);
6440 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6442 r_framedata_current = 0;
6443 r_framedata_failed = false;
6446 void *R_FrameData_Alloc(size_t size)
6450 // align to 16 byte boundary
6451 size = (size + 15) & ~15;
6452 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6453 r_framedata_current += size;
6456 if (r_framedata_current > r_framedata_size)
6457 r_framedata_failed = true;
6459 // return NULL on everything after a failure
6460 if (r_framedata_failed)
6466 void *R_FrameData_Store(size_t size, void *data)
6468 void *d = R_FrameData_Alloc(size);
6470 memcpy(d, data, size);
6474 //==================================================================================
6476 // LordHavoc: animcache originally written by Echon, rewritten since then
6479 * Animation cache prevents re-generating mesh data for an animated model
6480 * multiple times in one frame for lighting, shadowing, reflections, etc.
6483 void R_AnimCache_Free(void)
6487 void R_AnimCache_ClearCache(void)
6490 entity_render_t *ent;
6492 for (i = 0;i < r_refdef.scene.numentities;i++)
6494 ent = r_refdef.scene.entities[i];
6495 ent->animcache_vertex3f = NULL;
6496 ent->animcache_normal3f = NULL;
6497 ent->animcache_svector3f = NULL;
6498 ent->animcache_tvector3f = NULL;
6502 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6504 dp_model_t *model = ent->model;
6506 // see if it's already cached this frame
6507 if (ent->animcache_vertex3f)
6509 // add normals/tangents if needed
6510 if (wantnormals || wanttangents)
6512 if (ent->animcache_normal3f)
6513 wantnormals = false;
6514 if (ent->animcache_svector3f)
6515 wanttangents = false;
6516 if (wantnormals || wanttangents)
6518 numvertices = model->surfmesh.num_vertices;
6520 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6523 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6524 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6526 if (!r_framedata_failed)
6527 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6533 // see if this ent is worth caching
6534 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6536 // get some memory for this entity and generate mesh data
6537 numvertices = model->surfmesh.num_vertices;
6538 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6540 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6543 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6544 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6546 if (!r_framedata_failed)
6547 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6549 return !r_framedata_failed;
6552 void R_AnimCache_CacheVisibleEntities(void)
6555 qboolean wantnormals = !r_showsurfaces.integer;
6556 qboolean wanttangents = !r_showsurfaces.integer;
6558 switch(vid.renderpath)
6560 case RENDERPATH_GL20:
6561 case RENDERPATH_CGGL:
6563 case RENDERPATH_GL13:
6564 case RENDERPATH_GL11:
6565 wanttangents = false;
6569 // TODO: thread this
6570 // NOTE: R_PrepareRTLights() also caches entities
6572 for (i = 0;i < r_refdef.scene.numentities;i++)
6573 if (r_refdef.viewcache.entityvisible[i])
6574 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6576 if (r_shadows.integer)
6577 for (i = 0;i < r_refdef.scene.numentities;i++)
6578 if (!r_refdef.viewcache.entityvisible[i])
6579 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6582 //==================================================================================
6584 static void R_View_UpdateEntityLighting (void)
6587 entity_render_t *ent;
6588 vec3_t tempdiffusenormal, avg;
6589 vec_t f, fa, fd, fdd;
6591 for (i = 0;i < r_refdef.scene.numentities;i++)
6593 ent = r_refdef.scene.entities[i];
6595 // skip unseen models
6596 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6600 if (ent->model && ent->model->brush.num_leafs)
6602 // TODO: use modellight for r_ambient settings on world?
6603 VectorSet(ent->modellight_ambient, 0, 0, 0);
6604 VectorSet(ent->modellight_diffuse, 0, 0, 0);
6605 VectorSet(ent->modellight_lightdir, 0, 0, 1);
6609 // fetch the lighting from the worldmodel data
6610 VectorClear(ent->modellight_ambient);
6611 VectorClear(ent->modellight_diffuse);
6612 VectorClear(tempdiffusenormal);
6613 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6616 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6617 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6618 if(ent->flags & RENDER_EQUALIZE)
6620 // first fix up ambient lighting...
6621 if(r_equalize_entities_minambient.value > 0)
6623 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6626 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6627 if(fa < r_equalize_entities_minambient.value * fd)
6630 // fa'/fd' = minambient
6631 // fa'+0.25*fd' = fa+0.25*fd
6633 // fa' = fd' * minambient
6634 // fd'*(0.25+minambient) = fa+0.25*fd
6636 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6637 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6639 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6640 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
6641 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6642 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6647 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6649 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6650 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6653 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6654 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6655 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6661 VectorSet(ent->modellight_ambient, 1, 1, 1);
6663 // move the light direction into modelspace coordinates for lighting code
6664 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6665 if(VectorLength2(ent->modellight_lightdir) == 0)
6666 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6667 VectorNormalize(ent->modellight_lightdir);
6671 #define MAX_LINEOFSIGHTTRACES 64
6673 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6676 vec3_t boxmins, boxmaxs;
6679 dp_model_t *model = r_refdef.scene.worldmodel;
6681 if (!model || !model->brush.TraceLineOfSight)
6684 // expand the box a little
6685 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6686 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6687 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6688 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6689 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6690 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6692 // return true if eye is inside enlarged box
6693 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6697 VectorCopy(eye, start);
6698 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6699 if (model->brush.TraceLineOfSight(model, start, end))
6702 // try various random positions
6703 for (i = 0;i < numsamples;i++)
6705 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6706 if (model->brush.TraceLineOfSight(model, start, end))
6714 static void R_View_UpdateEntityVisible (void)
6719 entity_render_t *ent;
6721 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6722 if (!r_drawviewmodel.integer)
6723 renderimask |= RENDER_VIEWMODEL;
6724 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6726 // worldmodel can check visibility
6727 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6728 for (i = 0;i < r_refdef.scene.numentities;i++)
6730 ent = r_refdef.scene.entities[i];
6731 if (!(ent->flags & renderimask))
6732 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)))
6733 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))
6734 r_refdef.viewcache.entityvisible[i] = true;
6736 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6738 for (i = 0;i < r_refdef.scene.numentities;i++)
6740 ent = r_refdef.scene.entities[i];
6741 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6743 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6745 continue; // temp entities do pvs only
6746 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6747 ent->last_trace_visibility = realtime;
6748 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6749 r_refdef.viewcache.entityvisible[i] = 0;
6756 // no worldmodel or it can't check visibility
6757 for (i = 0;i < r_refdef.scene.numentities;i++)
6759 ent = r_refdef.scene.entities[i];
6760 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));
6765 /// only used if skyrendermasked, and normally returns false
6766 int R_DrawBrushModelsSky (void)
6769 entity_render_t *ent;
6772 for (i = 0;i < r_refdef.scene.numentities;i++)
6774 if (!r_refdef.viewcache.entityvisible[i])
6776 ent = r_refdef.scene.entities[i];
6777 if (!ent->model || !ent->model->DrawSky)
6779 ent->model->DrawSky(ent);
6785 static void R_DrawNoModel(entity_render_t *ent);
6786 static void R_DrawModels(void)
6789 entity_render_t *ent;
6791 for (i = 0;i < r_refdef.scene.numentities;i++)
6793 if (!r_refdef.viewcache.entityvisible[i])
6795 ent = r_refdef.scene.entities[i];
6796 r_refdef.stats.entities++;
6797 if (ent->model && ent->model->Draw != NULL)
6798 ent->model->Draw(ent);
6804 static void R_DrawModelsDepth(void)
6807 entity_render_t *ent;
6809 for (i = 0;i < r_refdef.scene.numentities;i++)
6811 if (!r_refdef.viewcache.entityvisible[i])
6813 ent = r_refdef.scene.entities[i];
6814 if (ent->model && ent->model->DrawDepth != NULL)
6815 ent->model->DrawDepth(ent);
6819 static void R_DrawModelsDebug(void)
6822 entity_render_t *ent;
6824 for (i = 0;i < r_refdef.scene.numentities;i++)
6826 if (!r_refdef.viewcache.entityvisible[i])
6828 ent = r_refdef.scene.entities[i];
6829 if (ent->model && ent->model->DrawDebug != NULL)
6830 ent->model->DrawDebug(ent);
6834 static void R_DrawModelsAddWaterPlanes(void)
6837 entity_render_t *ent;
6839 for (i = 0;i < r_refdef.scene.numentities;i++)
6841 if (!r_refdef.viewcache.entityvisible[i])
6843 ent = r_refdef.scene.entities[i];
6844 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6845 ent->model->DrawAddWaterPlanes(ent);
6849 static void R_View_SetFrustum(void)
6852 double slopex, slopey;
6853 vec3_t forward, left, up, origin;
6855 // we can't trust r_refdef.view.forward and friends in reflected scenes
6856 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6859 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6860 r_refdef.view.frustum[0].normal[1] = 0 - 0;
6861 r_refdef.view.frustum[0].normal[2] = -1 - 0;
6862 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6863 r_refdef.view.frustum[1].normal[1] = 0 + 0;
6864 r_refdef.view.frustum[1].normal[2] = -1 + 0;
6865 r_refdef.view.frustum[2].normal[0] = 0 - 0;
6866 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6867 r_refdef.view.frustum[2].normal[2] = -1 - 0;
6868 r_refdef.view.frustum[3].normal[0] = 0 + 0;
6869 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6870 r_refdef.view.frustum[3].normal[2] = -1 + 0;
6874 zNear = r_refdef.nearclip;
6875 nudge = 1.0 - 1.0 / (1<<23);
6876 r_refdef.view.frustum[4].normal[0] = 0 - 0;
6877 r_refdef.view.frustum[4].normal[1] = 0 - 0;
6878 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6879 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6880 r_refdef.view.frustum[5].normal[0] = 0 + 0;
6881 r_refdef.view.frustum[5].normal[1] = 0 + 0;
6882 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6883 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6889 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6890 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6891 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6892 r_refdef.view.frustum[0].dist = m[15] - m[12];
6894 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6895 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6896 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6897 r_refdef.view.frustum[1].dist = m[15] + m[12];
6899 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6900 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6901 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6902 r_refdef.view.frustum[2].dist = m[15] - m[13];
6904 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6905 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6906 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6907 r_refdef.view.frustum[3].dist = m[15] + m[13];
6909 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6910 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6911 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6912 r_refdef.view.frustum[4].dist = m[15] - m[14];
6914 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6915 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6916 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6917 r_refdef.view.frustum[5].dist = m[15] + m[14];
6920 if (r_refdef.view.useperspective)
6922 slopex = 1.0 / r_refdef.view.frustum_x;
6923 slopey = 1.0 / r_refdef.view.frustum_y;
6924 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6925 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
6926 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
6927 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
6928 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6930 // Leaving those out was a mistake, those were in the old code, and they
6931 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6932 // I couldn't reproduce it after adding those normalizations. --blub
6933 VectorNormalize(r_refdef.view.frustum[0].normal);
6934 VectorNormalize(r_refdef.view.frustum[1].normal);
6935 VectorNormalize(r_refdef.view.frustum[2].normal);
6936 VectorNormalize(r_refdef.view.frustum[3].normal);
6938 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6939 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]);
6940 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]);
6941 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]);
6942 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]);
6944 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6945 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6946 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6947 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6948 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6952 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6953 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6954 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6955 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6956 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6957 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6958 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6959 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6960 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6961 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6963 r_refdef.view.numfrustumplanes = 5;
6965 if (r_refdef.view.useclipplane)
6967 r_refdef.view.numfrustumplanes = 6;
6968 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6971 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6972 PlaneClassify(r_refdef.view.frustum + i);
6974 // LordHavoc: note to all quake engine coders, Quake had a special case
6975 // for 90 degrees which assumed a square view (wrong), so I removed it,
6976 // Quake2 has it disabled as well.
6978 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6979 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6980 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6981 //PlaneClassify(&frustum[0]);
6983 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6984 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6985 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6986 //PlaneClassify(&frustum[1]);
6988 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6989 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6990 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6991 //PlaneClassify(&frustum[2]);
6993 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6994 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6995 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6996 //PlaneClassify(&frustum[3]);
6999 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7000 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7001 //PlaneClassify(&frustum[4]);
7004 void R_View_Update(void)
7006 R_Main_ResizeViewCache();
7007 R_View_SetFrustum();
7008 R_View_WorldVisibility(r_refdef.view.useclipplane);
7009 R_View_UpdateEntityVisible();
7010 R_View_UpdateEntityLighting();
7013 void R_SetupView(qboolean allowwaterclippingplane)
7015 const float *customclipplane = NULL;
7017 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7019 // LordHavoc: couldn't figure out how to make this approach the
7020 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7021 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7022 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7023 dist = r_refdef.view.clipplane.dist;
7024 plane[0] = r_refdef.view.clipplane.normal[0];
7025 plane[1] = r_refdef.view.clipplane.normal[1];
7026 plane[2] = r_refdef.view.clipplane.normal[2];
7028 customclipplane = plane;
7031 if (!r_refdef.view.useperspective)
7032 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);
7033 else if (vid.stencil && r_useinfinitefarclip.integer)
7034 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);
7036 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);
7037 R_SetViewport(&r_refdef.view.viewport);
7040 void R_EntityMatrix(const matrix4x4_t *matrix)
7042 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7044 gl_modelmatrixchanged = false;
7045 gl_modelmatrix = *matrix;
7046 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7047 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7048 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7049 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7051 switch(vid.renderpath)
7053 case RENDERPATH_GL20:
7054 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7055 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7056 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7058 case RENDERPATH_CGGL:
7061 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7062 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7063 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7066 case RENDERPATH_GL13:
7067 case RENDERPATH_GL11:
7068 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7074 void R_ResetViewRendering2D(void)
7076 r_viewport_t viewport;
7079 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7080 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);
7081 R_SetViewport(&viewport);
7082 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7083 GL_Color(1, 1, 1, 1);
7084 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7085 GL_BlendFunc(GL_ONE, GL_ZERO);
7086 GL_AlphaTest(false);
7087 GL_ScissorTest(false);
7088 GL_DepthMask(false);
7089 GL_DepthRange(0, 1);
7090 GL_DepthTest(false);
7091 R_EntityMatrix(&identitymatrix);
7092 R_Mesh_ResetTextureState();
7093 GL_PolygonOffset(0, 0);
7094 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7095 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7096 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7097 qglStencilMask(~0);CHECKGLERROR
7098 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7099 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7100 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7103 void R_ResetViewRendering3D(void)
7108 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7109 GL_Color(1, 1, 1, 1);
7110 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7111 GL_BlendFunc(GL_ONE, GL_ZERO);
7112 GL_AlphaTest(false);
7113 GL_ScissorTest(true);
7115 GL_DepthRange(0, 1);
7117 R_EntityMatrix(&identitymatrix);
7118 R_Mesh_ResetTextureState();
7119 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7120 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7121 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7122 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7123 qglStencilMask(~0);CHECKGLERROR
7124 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7125 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7126 GL_CullFace(r_refdef.view.cullface_back);
7129 void R_RenderScene(void);
7130 void R_RenderWaterPlanes(void);
7132 static void R_Water_StartFrame(void)
7135 int waterwidth, waterheight, texturewidth, textureheight;
7136 r_waterstate_waterplane_t *p;
7138 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7141 switch(vid.renderpath)
7143 case RENDERPATH_GL20:
7144 case RENDERPATH_CGGL:
7146 case RENDERPATH_GL13:
7147 case RENDERPATH_GL11:
7151 // set waterwidth and waterheight to the water resolution that will be
7152 // used (often less than the screen resolution for faster rendering)
7153 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7154 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7156 // calculate desired texture sizes
7157 // can't use water if the card does not support the texture size
7158 if (!r_water.integer || r_showsurfaces.integer)
7159 texturewidth = textureheight = waterwidth = waterheight = 0;
7160 else if (vid.support.arb_texture_non_power_of_two)
7162 texturewidth = waterwidth;
7163 textureheight = waterheight;
7167 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
7168 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
7171 // allocate textures as needed
7172 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
7174 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7175 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7177 if (p->texture_refraction)
7178 R_FreeTexture(p->texture_refraction);
7179 p->texture_refraction = NULL;
7180 if (p->texture_reflection)
7181 R_FreeTexture(p->texture_reflection);
7182 p->texture_reflection = NULL;
7184 memset(&r_waterstate, 0, sizeof(r_waterstate));
7185 r_waterstate.texturewidth = texturewidth;
7186 r_waterstate.textureheight = textureheight;
7189 if (r_waterstate.texturewidth)
7191 r_waterstate.enabled = true;
7193 // when doing a reduced render (HDR) we want to use a smaller area
7194 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7195 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7197 // set up variables that will be used in shader setup
7198 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7199 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7200 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7201 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7204 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7205 r_waterstate.numwaterplanes = 0;
7208 void R_Water_AddWaterPlane(msurface_t *surface)
7210 int triangleindex, planeindex;
7216 r_waterstate_waterplane_t *p;
7217 texture_t *t = R_GetCurrentTexture(surface->texture);
7218 // just use the first triangle with a valid normal for any decisions
7219 VectorClear(normal);
7220 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7222 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7223 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7224 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7225 TriangleNormal(vert[0], vert[1], vert[2], normal);
7226 if (VectorLength2(normal) >= 0.001)
7230 VectorCopy(normal, plane.normal);
7231 VectorNormalize(plane.normal);
7232 plane.dist = DotProduct(vert[0], plane.normal);
7233 PlaneClassify(&plane);
7234 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7236 // skip backfaces (except if nocullface is set)
7237 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7239 VectorNegate(plane.normal, plane.normal);
7241 PlaneClassify(&plane);
7245 // find a matching plane if there is one
7246 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7247 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7249 if (planeindex >= r_waterstate.maxwaterplanes)
7250 return; // nothing we can do, out of planes
7252 // if this triangle does not fit any known plane rendered this frame, add one
7253 if (planeindex >= r_waterstate.numwaterplanes)
7255 // store the new plane
7256 r_waterstate.numwaterplanes++;
7258 // clear materialflags and pvs
7259 p->materialflags = 0;
7260 p->pvsvalid = false;
7262 // merge this surface's materialflags into the waterplane
7263 p->materialflags |= t->currentmaterialflags;
7264 // merge this surface's PVS into the waterplane
7265 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7266 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7267 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7269 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7274 static void R_Water_ProcessPlanes(void)
7276 r_refdef_view_t originalview;
7277 r_refdef_view_t myview;
7279 r_waterstate_waterplane_t *p;
7281 originalview = r_refdef.view;
7283 // make sure enough textures are allocated
7284 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7286 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7288 if (!p->texture_refraction)
7289 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);
7290 if (!p->texture_refraction)
7294 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7296 if (!p->texture_reflection)
7297 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);
7298 if (!p->texture_reflection)
7304 r_refdef.view = originalview;
7305 r_refdef.view.showdebug = false;
7306 r_refdef.view.width = r_waterstate.waterwidth;
7307 r_refdef.view.height = r_waterstate.waterheight;
7308 r_refdef.view.useclipplane = true;
7309 myview = r_refdef.view;
7310 r_waterstate.renderingscene = true;
7311 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7313 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7315 r_refdef.view = myview;
7316 // render reflected scene and copy into texture
7317 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7318 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7319 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7320 r_refdef.view.clipplane = p->plane;
7321 // reverse the cullface settings for this render
7322 r_refdef.view.cullface_front = GL_FRONT;
7323 r_refdef.view.cullface_back = GL_BACK;
7324 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7326 r_refdef.view.usecustompvs = true;
7328 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7330 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7333 R_ResetViewRendering3D();
7334 R_ClearScreen(r_refdef.fogenabled);
7338 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);
7341 // render the normal view scene and copy into texture
7342 // (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)
7343 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7345 r_refdef.view = myview;
7346 r_refdef.view.clipplane = p->plane;
7347 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7348 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7349 PlaneClassify(&r_refdef.view.clipplane);
7351 R_ResetViewRendering3D();
7352 R_ClearScreen(r_refdef.fogenabled);
7356 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);
7360 r_waterstate.renderingscene = false;
7361 r_refdef.view = originalview;
7362 R_ResetViewRendering3D();
7363 R_ClearScreen(r_refdef.fogenabled);
7367 r_refdef.view = originalview;
7368 r_waterstate.renderingscene = false;
7369 Cvar_SetValueQuick(&r_water, 0);
7370 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
7374 void R_Bloom_StartFrame(void)
7376 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7378 switch(vid.renderpath)
7380 case RENDERPATH_GL20:
7381 case RENDERPATH_CGGL:
7383 case RENDERPATH_GL13:
7384 case RENDERPATH_GL11:
7388 // set bloomwidth and bloomheight to the bloom resolution that will be
7389 // used (often less than the screen resolution for faster rendering)
7390 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7391 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7392 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7393 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7394 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7396 // calculate desired texture sizes
7397 if (vid.support.arb_texture_non_power_of_two)
7399 screentexturewidth = r_refdef.view.width;
7400 screentextureheight = r_refdef.view.height;
7401 bloomtexturewidth = r_bloomstate.bloomwidth;
7402 bloomtextureheight = r_bloomstate.bloomheight;
7406 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
7407 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
7408 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
7409 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
7412 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))
7414 Cvar_SetValueQuick(&r_hdr, 0);
7415 Cvar_SetValueQuick(&r_bloom, 0);
7416 Cvar_SetValueQuick(&r_motionblur, 0);
7417 Cvar_SetValueQuick(&r_damageblur, 0);
7420 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)))
7421 screentexturewidth = screentextureheight = 0;
7422 if (!r_hdr.integer && !r_bloom.integer)
7423 bloomtexturewidth = bloomtextureheight = 0;
7425 // allocate textures as needed
7426 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7428 if (r_bloomstate.texture_screen)
7429 R_FreeTexture(r_bloomstate.texture_screen);
7430 r_bloomstate.texture_screen = NULL;
7431 r_bloomstate.screentexturewidth = screentexturewidth;
7432 r_bloomstate.screentextureheight = screentextureheight;
7433 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7434 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7436 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7438 if (r_bloomstate.texture_bloom)
7439 R_FreeTexture(r_bloomstate.texture_bloom);
7440 r_bloomstate.texture_bloom = NULL;
7441 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7442 r_bloomstate.bloomtextureheight = bloomtextureheight;
7443 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7444 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7447 // when doing a reduced render (HDR) we want to use a smaller area
7448 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7449 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7450 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7451 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7452 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7454 // set up a texcoord array for the full resolution screen image
7455 // (we have to keep this around to copy back during final render)
7456 r_bloomstate.screentexcoord2f[0] = 0;
7457 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7458 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7459 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7460 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7461 r_bloomstate.screentexcoord2f[5] = 0;
7462 r_bloomstate.screentexcoord2f[6] = 0;
7463 r_bloomstate.screentexcoord2f[7] = 0;
7465 // set up a texcoord array for the reduced resolution bloom image
7466 // (which will be additive blended over the screen image)
7467 r_bloomstate.bloomtexcoord2f[0] = 0;
7468 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7469 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7470 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7471 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7472 r_bloomstate.bloomtexcoord2f[5] = 0;
7473 r_bloomstate.bloomtexcoord2f[6] = 0;
7474 r_bloomstate.bloomtexcoord2f[7] = 0;
7476 if (r_hdr.integer || r_bloom.integer)
7478 r_bloomstate.enabled = true;
7479 r_bloomstate.hdr = r_hdr.integer != 0;
7482 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);
7485 void R_Bloom_CopyBloomTexture(float colorscale)
7487 r_refdef.stats.bloom++;
7489 // scale down screen texture to the bloom texture size
7491 R_SetViewport(&r_bloomstate.viewport);
7492 GL_BlendFunc(GL_ONE, GL_ZERO);
7493 GL_Color(colorscale, colorscale, colorscale, 1);
7494 // TODO: optimize with multitexture or GLSL
7495 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7496 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7497 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7498 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7500 // we now have a bloom image in the framebuffer
7501 // copy it into the bloom image texture for later processing
7502 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);
7503 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7506 void R_Bloom_CopyHDRTexture(void)
7508 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);
7509 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7512 void R_Bloom_MakeTexture(void)
7515 float xoffset, yoffset, r, brighten;
7517 r_refdef.stats.bloom++;
7519 R_ResetViewRendering2D();
7520 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7521 R_Mesh_ColorPointer(NULL, 0, 0);
7523 // we have a bloom image in the framebuffer
7525 R_SetViewport(&r_bloomstate.viewport);
7527 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7530 r = bound(0, r_bloom_colorexponent.value / x, 1);
7531 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7532 GL_Color(r, r, r, 1);
7533 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7534 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7535 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7536 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7538 // copy the vertically blurred bloom view to a texture
7539 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);
7540 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7543 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7544 brighten = r_bloom_brighten.value;
7546 brighten *= r_hdr_range.value;
7547 brighten = sqrt(brighten);
7549 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7550 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7551 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7553 for (dir = 0;dir < 2;dir++)
7555 // blend on at multiple vertical offsets to achieve a vertical blur
7556 // TODO: do offset blends using GLSL
7557 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7558 GL_BlendFunc(GL_ONE, GL_ZERO);
7559 for (x = -range;x <= range;x++)
7561 if (!dir){xoffset = 0;yoffset = x;}
7562 else {xoffset = x;yoffset = 0;}
7563 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7564 yoffset /= (float)r_bloomstate.bloomtextureheight;
7565 // compute a texcoord array with the specified x and y offset
7566 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7567 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7568 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7569 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7570 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7571 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7572 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7573 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7574 // this r value looks like a 'dot' particle, fading sharply to
7575 // black at the edges
7576 // (probably not realistic but looks good enough)
7577 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7578 //r = brighten/(range*2+1);
7579 r = brighten / (range * 2 + 1);
7581 r *= (1 - x*x/(float)(range*range));
7582 GL_Color(r, r, r, 1);
7583 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7584 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7585 GL_BlendFunc(GL_ONE, GL_ONE);
7588 // copy the vertically blurred bloom view to a texture
7589 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);
7590 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7593 // apply subtract last
7594 // (just like it would be in a GLSL shader)
7595 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7597 GL_BlendFunc(GL_ONE, GL_ZERO);
7598 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7599 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7600 GL_Color(1, 1, 1, 1);
7601 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7602 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7604 GL_BlendFunc(GL_ONE, GL_ONE);
7605 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7606 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7607 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7608 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7609 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7610 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7611 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7613 // copy the darkened bloom view to a texture
7614 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);
7615 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7619 void R_HDR_RenderBloomTexture(void)
7621 int oldwidth, oldheight;
7622 float oldcolorscale;
7624 oldcolorscale = r_refdef.view.colorscale;
7625 oldwidth = r_refdef.view.width;
7626 oldheight = r_refdef.view.height;
7627 r_refdef.view.width = r_bloomstate.bloomwidth;
7628 r_refdef.view.height = r_bloomstate.bloomheight;
7630 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
7631 // TODO: add exposure compensation features
7632 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7634 r_refdef.view.showdebug = false;
7635 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7637 R_ResetViewRendering3D();
7639 R_ClearScreen(r_refdef.fogenabled);
7640 if (r_timereport_active)
7641 R_TimeReport("HDRclear");
7644 if (r_timereport_active)
7645 R_TimeReport("visibility");
7647 // only do secondary renders with HDR if r_hdr is 2 or higher
7648 r_waterstate.numwaterplanes = 0;
7649 if (r_waterstate.enabled && r_hdr.integer >= 2)
7650 R_RenderWaterPlanes();
7652 r_refdef.view.showdebug = true;
7654 r_waterstate.numwaterplanes = 0;
7656 R_ResetViewRendering2D();
7658 R_Bloom_CopyHDRTexture();
7659 R_Bloom_MakeTexture();
7661 // restore the view settings
7662 r_refdef.view.width = oldwidth;
7663 r_refdef.view.height = oldheight;
7664 r_refdef.view.colorscale = oldcolorscale;
7666 R_ResetViewRendering3D();
7668 R_ClearScreen(r_refdef.fogenabled);
7669 if (r_timereport_active)
7670 R_TimeReport("viewclear");
7673 static void R_BlendView(void)
7675 unsigned int permutation;
7676 float uservecs[4][4];
7678 switch (vid.renderpath)
7680 case RENDERPATH_GL20:
7681 case RENDERPATH_CGGL:
7683 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7684 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7685 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7686 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7687 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7689 if (r_bloomstate.texture_screen)
7691 // make sure the buffer is available
7692 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7694 R_ResetViewRendering2D();
7695 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7696 R_Mesh_ColorPointer(NULL, 0, 0);
7698 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7700 // declare variables
7702 static float avgspeed;
7704 speed = VectorLength(cl.movement_velocity);
7706 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7707 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7709 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7710 speed = bound(0, speed, 1);
7711 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7713 // calculate values into a standard alpha
7714 cl.motionbluralpha = 1 - exp(-
7716 (r_motionblur.value * speed / 80)
7718 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7721 max(0.0001, cl.time - cl.oldtime) // fps independent
7724 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7725 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7727 if (cl.motionbluralpha > 0)
7729 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7730 GL_Color(1, 1, 1, cl.motionbluralpha);
7731 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7732 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7733 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7734 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7738 // copy view into the screen texture
7739 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);
7740 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7742 else if (!r_bloomstate.texture_bloom)
7744 // we may still have to do view tint...
7745 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7747 // apply a color tint to the whole view
7748 R_ResetViewRendering2D();
7749 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7750 R_Mesh_ColorPointer(NULL, 0, 0);
7751 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7752 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7753 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7754 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7756 break; // no screen processing, no bloom, skip it
7759 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7761 // render simple bloom effect
7762 // copy the screen and shrink it and darken it for the bloom process
7763 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7764 // make the bloom texture
7765 R_Bloom_MakeTexture();
7768 #if _MSC_VER >= 1400
7769 #define sscanf sscanf_s
7771 memset(uservecs, 0, sizeof(uservecs));
7772 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7773 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7774 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7775 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7777 R_ResetViewRendering2D();
7778 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7779 R_Mesh_ColorPointer(NULL, 0, 0);
7780 GL_Color(1, 1, 1, 1);
7781 GL_BlendFunc(GL_ONE, GL_ZERO);
7782 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7783 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7785 switch(vid.renderpath)
7787 case RENDERPATH_GL20:
7788 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7789 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
7790 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
7791 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7792 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]);
7793 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7794 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]);
7795 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]);
7796 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]);
7797 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]);
7798 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7799 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7801 case RENDERPATH_CGGL:
7803 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7804 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
7805 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
7806 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
7807 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
7808 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7809 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
7810 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
7811 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
7812 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
7813 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
7814 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7820 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7821 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7823 case RENDERPATH_GL13:
7824 case RENDERPATH_GL11:
7825 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7827 // apply a color tint to the whole view
7828 R_ResetViewRendering2D();
7829 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7830 R_Mesh_ColorPointer(NULL, 0, 0);
7831 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7832 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7833 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7834 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7840 matrix4x4_t r_waterscrollmatrix;
7842 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7844 if (r_refdef.fog_density)
7846 r_refdef.fogcolor[0] = r_refdef.fog_red;
7847 r_refdef.fogcolor[1] = r_refdef.fog_green;
7848 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7850 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7851 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7852 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7853 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7857 VectorCopy(r_refdef.fogcolor, fogvec);
7858 // color.rgb *= ContrastBoost * SceneBrightness;
7859 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7860 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7861 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7862 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7867 void R_UpdateVariables(void)
7871 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7873 r_refdef.farclip = r_farclip_base.value;
7874 if (r_refdef.scene.worldmodel)
7875 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7876 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7878 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7879 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7880 r_refdef.polygonfactor = 0;
7881 r_refdef.polygonoffset = 0;
7882 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7883 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7885 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7886 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7887 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7888 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7889 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7890 if (r_showsurfaces.integer)
7892 r_refdef.scene.rtworld = false;
7893 r_refdef.scene.rtworldshadows = false;
7894 r_refdef.scene.rtdlight = false;
7895 r_refdef.scene.rtdlightshadows = false;
7896 r_refdef.lightmapintensity = 0;
7899 if (gamemode == GAME_NEHAHRA)
7901 if (gl_fogenable.integer)
7903 r_refdef.oldgl_fogenable = true;
7904 r_refdef.fog_density = gl_fogdensity.value;
7905 r_refdef.fog_red = gl_fogred.value;
7906 r_refdef.fog_green = gl_foggreen.value;
7907 r_refdef.fog_blue = gl_fogblue.value;
7908 r_refdef.fog_alpha = 1;
7909 r_refdef.fog_start = 0;
7910 r_refdef.fog_end = gl_skyclip.value;
7911 r_refdef.fog_height = 1<<30;
7912 r_refdef.fog_fadedepth = 128;
7914 else if (r_refdef.oldgl_fogenable)
7916 r_refdef.oldgl_fogenable = false;
7917 r_refdef.fog_density = 0;
7918 r_refdef.fog_red = 0;
7919 r_refdef.fog_green = 0;
7920 r_refdef.fog_blue = 0;
7921 r_refdef.fog_alpha = 0;
7922 r_refdef.fog_start = 0;
7923 r_refdef.fog_end = 0;
7924 r_refdef.fog_height = 1<<30;
7925 r_refdef.fog_fadedepth = 128;
7929 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7930 r_refdef.fog_start = max(0, r_refdef.fog_start);
7931 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7933 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7935 if (r_refdef.fog_density && r_drawfog.integer)
7937 r_refdef.fogenabled = true;
7938 // this is the point where the fog reaches 0.9986 alpha, which we
7939 // consider a good enough cutoff point for the texture
7940 // (0.9986 * 256 == 255.6)
7941 if (r_fog_exp2.integer)
7942 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7944 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7945 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7946 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7947 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7948 // fog color was already set
7949 // update the fog texture
7950 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)
7951 R_BuildFogTexture();
7954 r_refdef.fogenabled = false;
7956 switch(vid.renderpath)
7958 case RENDERPATH_GL20:
7959 case RENDERPATH_CGGL:
7960 if(v_glslgamma.integer && !vid_gammatables_trivial)
7962 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7964 // build GLSL gamma texture
7965 #define RAMPWIDTH 256
7966 unsigned short ramp[RAMPWIDTH * 3];
7967 unsigned char rampbgr[RAMPWIDTH][4];
7970 r_texture_gammaramps_serial = vid_gammatables_serial;
7972 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7973 for(i = 0; i < RAMPWIDTH; ++i)
7975 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7976 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7977 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7980 if (r_texture_gammaramps)
7982 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7986 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);
7992 // remove GLSL gamma texture
7995 case RENDERPATH_GL13:
7996 case RENDERPATH_GL11:
8001 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8002 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8008 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8009 if( scenetype != r_currentscenetype ) {
8010 // store the old scenetype
8011 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8012 r_currentscenetype = scenetype;
8013 // move in the new scene
8014 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8023 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8025 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8026 if( scenetype == r_currentscenetype ) {
8027 return &r_refdef.scene;
8029 return &r_scenes_store[ scenetype ];
8038 void R_RenderView(void)
8040 if (r_timereport_active)
8041 R_TimeReport("start");
8042 r_textureframe++; // used only by R_GetCurrentTexture
8043 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8045 if (!r_drawentities.integer)
8046 r_refdef.scene.numentities = 0;
8048 R_AnimCache_ClearCache();
8049 R_FrameData_NewFrame();
8051 if (r_refdef.view.isoverlay)
8053 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8054 GL_Clear( GL_DEPTH_BUFFER_BIT );
8055 R_TimeReport("depthclear");
8057 r_refdef.view.showdebug = false;
8059 r_waterstate.enabled = false;
8060 r_waterstate.numwaterplanes = 0;
8068 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8069 return; //Host_Error ("R_RenderView: NULL worldmodel");
8071 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8073 // break apart the view matrix into vectors for various purposes
8074 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8075 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8076 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8077 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8078 // make an inverted copy of the view matrix for tracking sprites
8079 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8081 R_Shadow_UpdateWorldLightSelection();
8083 R_Bloom_StartFrame();
8084 R_Water_StartFrame();
8087 if (r_timereport_active)
8088 R_TimeReport("viewsetup");
8090 R_ResetViewRendering3D();
8092 if (r_refdef.view.clear || r_refdef.fogenabled)
8094 R_ClearScreen(r_refdef.fogenabled);
8095 if (r_timereport_active)
8096 R_TimeReport("viewclear");
8098 r_refdef.view.clear = true;
8100 // this produces a bloom texture to be used in R_BlendView() later
8101 if (r_hdr.integer && r_bloomstate.bloomwidth)
8103 R_HDR_RenderBloomTexture();
8104 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8105 r_textureframe++; // used only by R_GetCurrentTexture
8108 r_refdef.view.showdebug = true;
8111 if (r_timereport_active)
8112 R_TimeReport("visibility");
8114 r_waterstate.numwaterplanes = 0;
8115 if (r_waterstate.enabled)
8116 R_RenderWaterPlanes();
8119 r_waterstate.numwaterplanes = 0;
8122 if (r_timereport_active)
8123 R_TimeReport("blendview");
8125 GL_Scissor(0, 0, vid.width, vid.height);
8126 GL_ScissorTest(false);
8130 void R_RenderWaterPlanes(void)
8132 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8134 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8135 if (r_timereport_active)
8136 R_TimeReport("waterworld");
8139 // don't let sound skip if going slow
8140 if (r_refdef.scene.extraupdate)
8143 R_DrawModelsAddWaterPlanes();
8144 if (r_timereport_active)
8145 R_TimeReport("watermodels");
8147 if (r_waterstate.numwaterplanes)
8149 R_Water_ProcessPlanes();
8150 if (r_timereport_active)
8151 R_TimeReport("waterscenes");
8155 extern void R_DrawLightningBeams (void);
8156 extern void VM_CL_AddPolygonsToMeshQueue (void);
8157 extern void R_DrawPortals (void);
8158 extern cvar_t cl_locs_show;
8159 static void R_DrawLocs(void);
8160 static void R_DrawEntityBBoxes(void);
8161 static void R_DrawModelDecals(void);
8162 extern cvar_t cl_decals_newsystem;
8163 extern qboolean r_shadow_usingdeferredprepass;
8164 void R_RenderScene(void)
8166 r_refdef.stats.renders++;
8170 // don't let sound skip if going slow
8171 if (r_refdef.scene.extraupdate)
8174 R_MeshQueue_BeginScene();
8178 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);
8180 if (cl.csqc_vidvars.drawworld)
8182 // don't let sound skip if going slow
8183 if (r_refdef.scene.extraupdate)
8186 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8188 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8189 if (r_timereport_active)
8190 R_TimeReport("worldsky");
8193 if (R_DrawBrushModelsSky() && r_timereport_active)
8194 R_TimeReport("bmodelsky");
8196 if (skyrendermasked && skyrenderlater)
8198 // we have to force off the water clipping plane while rendering sky
8199 qboolean save = r_refdef.view.showdebug;
8201 r_refdef.view.showdebug = false;
8203 r_refdef.view.showdebug = save;
8205 if (r_timereport_active)
8206 R_TimeReport("sky");
8210 R_AnimCache_CacheVisibleEntities();
8211 if (r_timereport_active)
8212 R_TimeReport("animation");
8214 R_Shadow_PrepareLights();
8215 if (r_timereport_active)
8216 R_TimeReport("preparelights");
8218 if (r_shadow_usingdeferredprepass)
8219 R_Shadow_DrawPrepass();
8221 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8223 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8224 if (r_timereport_active)
8225 R_TimeReport("worlddepth");
8227 if (r_depthfirst.integer >= 2)
8229 R_DrawModelsDepth();
8230 if (r_timereport_active)
8231 R_TimeReport("modeldepth");
8234 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8236 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8237 if (r_timereport_active)
8238 R_TimeReport("world");
8241 // don't let sound skip if going slow
8242 if (r_refdef.scene.extraupdate)
8246 if (r_timereport_active)
8247 R_TimeReport("models");
8249 // don't let sound skip if going slow
8250 if (r_refdef.scene.extraupdate)
8253 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8255 R_DrawModelShadows();
8256 R_ResetViewRendering3D();
8257 // don't let sound skip if going slow
8258 if (r_refdef.scene.extraupdate)
8262 if (!r_shadow_usingdeferredprepass)
8264 R_Shadow_DrawLights();
8265 if (r_timereport_active)
8266 R_TimeReport("rtlights");
8269 // don't let sound skip if going slow
8270 if (r_refdef.scene.extraupdate)
8273 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8275 R_DrawModelShadows();
8276 R_ResetViewRendering3D();
8277 // don't let sound skip if going slow
8278 if (r_refdef.scene.extraupdate)
8282 if (cl.csqc_vidvars.drawworld)
8284 if (cl_decals_newsystem.integer)
8286 R_DrawModelDecals();
8287 if (r_timereport_active)
8288 R_TimeReport("modeldecals");
8293 if (r_timereport_active)
8294 R_TimeReport("decals");
8298 if (r_timereport_active)
8299 R_TimeReport("particles");
8302 if (r_timereport_active)
8303 R_TimeReport("explosions");
8305 R_DrawLightningBeams();
8306 if (r_timereport_active)
8307 R_TimeReport("lightning");
8310 VM_CL_AddPolygonsToMeshQueue();
8312 if (r_refdef.view.showdebug)
8314 if (cl_locs_show.integer)
8317 if (r_timereport_active)
8318 R_TimeReport("showlocs");
8321 if (r_drawportals.integer)
8324 if (r_timereport_active)
8325 R_TimeReport("portals");
8328 if (r_showbboxes.value > 0)
8330 R_DrawEntityBBoxes();
8331 if (r_timereport_active)
8332 R_TimeReport("bboxes");
8336 R_MeshQueue_RenderTransparent();
8337 if (r_timereport_active)
8338 R_TimeReport("drawtrans");
8340 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))
8342 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8343 if (r_timereport_active)
8344 R_TimeReport("worlddebug");
8345 R_DrawModelsDebug();
8346 if (r_timereport_active)
8347 R_TimeReport("modeldebug");
8350 if (cl.csqc_vidvars.drawworld)
8352 R_Shadow_DrawCoronas();
8353 if (r_timereport_active)
8354 R_TimeReport("coronas");
8357 // don't let sound skip if going slow
8358 if (r_refdef.scene.extraupdate)
8361 R_ResetViewRendering2D();
8364 static const unsigned short bboxelements[36] =
8374 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8377 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8379 RSurf_ActiveWorldEntity();
8381 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8382 GL_DepthMask(false);
8383 GL_DepthRange(0, 1);
8384 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8385 R_Mesh_ResetTextureState();
8387 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8388 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8389 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8390 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8391 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8392 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8393 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8394 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8395 R_FillColors(color4f, 8, cr, cg, cb, ca);
8396 if (r_refdef.fogenabled)
8398 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8400 f1 = RSurf_FogVertex(v);
8402 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8403 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8404 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8407 R_Mesh_VertexPointer(vertex3f, 0, 0);
8408 R_Mesh_ColorPointer(color4f, 0, 0);
8409 R_Mesh_ResetTextureState();
8410 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8411 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8414 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8418 prvm_edict_t *edict;
8419 prvm_prog_t *prog_save = prog;
8421 // this function draws bounding boxes of server entities
8425 GL_CullFace(GL_NONE);
8426 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8430 for (i = 0;i < numsurfaces;i++)
8432 edict = PRVM_EDICT_NUM(surfacelist[i]);
8433 switch ((int)edict->fields.server->solid)
8435 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
8436 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
8437 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
8438 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8439 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
8440 default: Vector4Set(color, 0, 0, 0, 0.50);break;
8442 color[3] *= r_showbboxes.value;
8443 color[3] = bound(0, color[3], 1);
8444 GL_DepthTest(!r_showdisabledepthtest.integer);
8445 GL_CullFace(r_refdef.view.cullface_front);
8446 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8452 static void R_DrawEntityBBoxes(void)
8455 prvm_edict_t *edict;
8457 prvm_prog_t *prog_save = prog;
8459 // this function draws bounding boxes of server entities
8465 for (i = 0;i < prog->num_edicts;i++)
8467 edict = PRVM_EDICT_NUM(i);
8468 if (edict->priv.server->free)
8470 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8471 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8473 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8475 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8476 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8482 static const int nomodelelement3i[24] =
8494 static const unsigned short nomodelelement3s[24] =
8506 static const float nomodelvertex3f[6*3] =
8516 static const float nomodelcolor4f[6*4] =
8518 0.0f, 0.0f, 0.5f, 1.0f,
8519 0.0f, 0.0f, 0.5f, 1.0f,
8520 0.0f, 0.5f, 0.0f, 1.0f,
8521 0.0f, 0.5f, 0.0f, 1.0f,
8522 0.5f, 0.0f, 0.0f, 1.0f,
8523 0.5f, 0.0f, 0.0f, 1.0f
8526 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8532 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);
8534 // this is only called once per entity so numsurfaces is always 1, and
8535 // surfacelist is always {0}, so this code does not handle batches
8537 if (rsurface.ent_flags & RENDER_ADDITIVE)
8539 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8540 GL_DepthMask(false);
8542 else if (rsurface.colormod[3] < 1)
8544 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8545 GL_DepthMask(false);
8549 GL_BlendFunc(GL_ONE, GL_ZERO);
8552 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8553 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8554 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8555 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8556 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8557 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8558 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8559 R_Mesh_ColorPointer(color4f, 0, 0);
8560 for (i = 0, c = color4f;i < 6;i++, c += 4)
8562 c[0] *= rsurface.colormod[0];
8563 c[1] *= rsurface.colormod[1];
8564 c[2] *= rsurface.colormod[2];
8565 c[3] *= rsurface.colormod[3];
8567 if (r_refdef.fogenabled)
8569 for (i = 0, c = color4f;i < 6;i++, c += 4)
8571 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8573 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8574 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8575 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8578 R_Mesh_ResetTextureState();
8579 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8582 void R_DrawNoModel(entity_render_t *ent)
8585 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8586 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8587 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8589 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8592 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8594 vec3_t right1, right2, diff, normal;
8596 VectorSubtract (org2, org1, normal);
8598 // calculate 'right' vector for start
8599 VectorSubtract (r_refdef.view.origin, org1, diff);
8600 CrossProduct (normal, diff, right1);
8601 VectorNormalize (right1);
8603 // calculate 'right' vector for end
8604 VectorSubtract (r_refdef.view.origin, org2, diff);
8605 CrossProduct (normal, diff, right2);
8606 VectorNormalize (right2);
8608 vert[ 0] = org1[0] + width * right1[0];
8609 vert[ 1] = org1[1] + width * right1[1];
8610 vert[ 2] = org1[2] + width * right1[2];
8611 vert[ 3] = org1[0] - width * right1[0];
8612 vert[ 4] = org1[1] - width * right1[1];
8613 vert[ 5] = org1[2] - width * right1[2];
8614 vert[ 6] = org2[0] - width * right2[0];
8615 vert[ 7] = org2[1] - width * right2[1];
8616 vert[ 8] = org2[2] - width * right2[2];
8617 vert[ 9] = org2[0] + width * right2[0];
8618 vert[10] = org2[1] + width * right2[1];
8619 vert[11] = org2[2] + width * right2[2];
8622 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)
8624 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8625 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8626 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8627 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8628 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8629 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8630 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8631 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8632 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8633 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8634 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8635 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8638 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8643 VectorSet(v, x, y, z);
8644 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8645 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8647 if (i == mesh->numvertices)
8649 if (mesh->numvertices < mesh->maxvertices)
8651 VectorCopy(v, vertex3f);
8652 mesh->numvertices++;
8654 return mesh->numvertices;
8660 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8664 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8665 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8666 e = mesh->element3i + mesh->numtriangles * 3;
8667 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8669 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8670 if (mesh->numtriangles < mesh->maxtriangles)
8675 mesh->numtriangles++;
8677 element[1] = element[2];
8681 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8685 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8686 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8687 e = mesh->element3i + mesh->numtriangles * 3;
8688 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8690 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8691 if (mesh->numtriangles < mesh->maxtriangles)
8696 mesh->numtriangles++;
8698 element[1] = element[2];
8702 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8703 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8705 int planenum, planenum2;
8708 mplane_t *plane, *plane2;
8710 double temppoints[2][256*3];
8711 // figure out how large a bounding box we need to properly compute this brush
8713 for (w = 0;w < numplanes;w++)
8714 maxdist = max(maxdist, fabs(planes[w].dist));
8715 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8716 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8717 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8721 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8722 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8724 if (planenum2 == planenum)
8726 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);
8729 if (tempnumpoints < 3)
8731 // generate elements forming a triangle fan for this polygon
8732 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8736 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)
8738 texturelayer_t *layer;
8739 layer = t->currentlayers + t->currentnumlayers++;
8741 layer->depthmask = depthmask;
8742 layer->blendfunc1 = blendfunc1;
8743 layer->blendfunc2 = blendfunc2;
8744 layer->texture = texture;
8745 layer->texmatrix = *matrix;
8746 layer->color[0] = r;
8747 layer->color[1] = g;
8748 layer->color[2] = b;
8749 layer->color[3] = a;
8752 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8755 index = parms[2] + r_refdef.scene.time * parms[3];
8756 index -= floor(index);
8760 case Q3WAVEFUNC_NONE:
8761 case Q3WAVEFUNC_NOISE:
8762 case Q3WAVEFUNC_COUNT:
8765 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8766 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8767 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8768 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8769 case Q3WAVEFUNC_TRIANGLE:
8771 f = index - floor(index);
8782 return (float)(parms[0] + parms[1] * f);
8785 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8790 matrix4x4_t matrix, temp;
8791 switch(tcmod->tcmod)
8795 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8796 matrix = r_waterscrollmatrix;
8798 matrix = identitymatrix;
8800 case Q3TCMOD_ENTITYTRANSLATE:
8801 // this is used in Q3 to allow the gamecode to control texcoord
8802 // scrolling on the entity, which is not supported in darkplaces yet.
8803 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8805 case Q3TCMOD_ROTATE:
8806 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8807 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8808 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8811 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8813 case Q3TCMOD_SCROLL:
8814 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8816 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8817 w = (int) tcmod->parms[0];
8818 h = (int) tcmod->parms[1];
8819 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8821 idx = (int) floor(f * w * h);
8822 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8824 case Q3TCMOD_STRETCH:
8825 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8826 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8828 case Q3TCMOD_TRANSFORM:
8829 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8830 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8831 VectorSet(tcmat + 6, 0 , 0 , 1);
8832 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8833 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8835 case Q3TCMOD_TURBULENT:
8836 // this is handled in the RSurf_PrepareVertices function
8837 matrix = identitymatrix;
8841 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8844 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8846 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8847 char name[MAX_QPATH];
8848 skinframe_t *skinframe;
8849 unsigned char pixels[296*194];
8850 strlcpy(cache->name, skinname, sizeof(cache->name));
8851 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8852 if (developer_loading.integer)
8853 Con_Printf("loading %s\n", name);
8854 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8855 if (!skinframe || !skinframe->base)
8858 fs_offset_t filesize;
8860 f = FS_LoadFile(name, tempmempool, true, &filesize);
8863 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8864 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8868 cache->skinframe = skinframe;
8871 texture_t *R_GetCurrentTexture(texture_t *t)
8874 const entity_render_t *ent = rsurface.entity;
8875 dp_model_t *model = ent->model;
8876 q3shaderinfo_layer_tcmod_t *tcmod;
8878 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8879 return t->currentframe;
8880 t->update_lastrenderframe = r_textureframe;
8881 t->update_lastrenderentity = (void *)ent;
8883 // switch to an alternate material if this is a q1bsp animated material
8885 texture_t *texture = t;
8886 int s = rsurface.ent_skinnum;
8887 if ((unsigned int)s >= (unsigned int)model->numskins)
8889 if (model->skinscenes)
8891 if (model->skinscenes[s].framecount > 1)
8892 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8894 s = model->skinscenes[s].firstframe;
8897 t = t + s * model->num_surfaces;
8900 // use an alternate animation if the entity's frame is not 0,
8901 // and only if the texture has an alternate animation
8902 if (rsurface.ent_alttextures && t->anim_total[1])
8903 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8905 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8907 texture->currentframe = t;
8910 // update currentskinframe to be a qw skin or animation frame
8911 if (rsurface.ent_qwskin >= 0)
8913 i = rsurface.ent_qwskin;
8914 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8916 r_qwskincache_size = cl.maxclients;
8918 Mem_Free(r_qwskincache);
8919 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8921 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8922 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8923 t->currentskinframe = r_qwskincache[i].skinframe;
8924 if (t->currentskinframe == NULL)
8925 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8927 else if (t->numskinframes >= 2)
8928 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8929 if (t->backgroundnumskinframes >= 2)
8930 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8932 t->currentmaterialflags = t->basematerialflags;
8933 t->currentalpha = rsurface.colormod[3];
8934 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8935 t->currentalpha *= r_wateralpha.value;
8936 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8937 t->currentalpha *= t->r_water_wateralpha;
8938 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8939 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8940 if (!(rsurface.ent_flags & RENDER_LIGHT))
8941 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8942 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8944 // pick a model lighting mode
8945 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8946 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8948 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8950 if (rsurface.ent_flags & RENDER_ADDITIVE)
8951 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8952 else if (t->currentalpha < 1)
8953 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8954 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8955 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8956 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8957 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8958 if (t->backgroundnumskinframes)
8959 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8960 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8962 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8963 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8966 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8967 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8968 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8970 // there is no tcmod
8971 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8973 t->currenttexmatrix = r_waterscrollmatrix;
8974 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8976 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8978 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8979 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8982 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8983 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8984 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8985 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8987 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8988 if (t->currentskinframe->qpixels)
8989 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8990 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8991 if (!t->basetexture)
8992 t->basetexture = r_texture_notexture;
8993 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8994 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8995 t->nmaptexture = t->currentskinframe->nmap;
8996 if (!t->nmaptexture)
8997 t->nmaptexture = r_texture_blanknormalmap;
8998 t->glosstexture = r_texture_black;
8999 t->glowtexture = t->currentskinframe->glow;
9000 t->fogtexture = t->currentskinframe->fog;
9001 t->reflectmasktexture = t->currentskinframe->reflect;
9002 if (t->backgroundnumskinframes)
9004 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9005 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9006 t->backgroundglosstexture = r_texture_black;
9007 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9008 if (!t->backgroundnmaptexture)
9009 t->backgroundnmaptexture = r_texture_blanknormalmap;
9013 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9014 t->backgroundnmaptexture = r_texture_blanknormalmap;
9015 t->backgroundglosstexture = r_texture_black;
9016 t->backgroundglowtexture = NULL;
9018 t->specularpower = r_shadow_glossexponent.value;
9019 // TODO: store reference values for these in the texture?
9020 t->specularscale = 0;
9021 if (r_shadow_gloss.integer > 0)
9023 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9025 if (r_shadow_glossintensity.value > 0)
9027 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9028 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9029 t->specularscale = r_shadow_glossintensity.value;
9032 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9034 t->glosstexture = r_texture_white;
9035 t->backgroundglosstexture = r_texture_white;
9036 t->specularscale = r_shadow_gloss2intensity.value;
9037 t->specularpower = r_shadow_gloss2exponent.value;
9040 t->specularscale *= t->specularscalemod;
9041 t->specularpower *= t->specularpowermod;
9043 // lightmaps mode looks bad with dlights using actual texturing, so turn
9044 // off the colormap and glossmap, but leave the normalmap on as it still
9045 // accurately represents the shading involved
9046 if (gl_lightmaps.integer)
9048 t->basetexture = r_texture_grey128;
9049 t->pantstexture = r_texture_black;
9050 t->shirttexture = r_texture_black;
9051 t->nmaptexture = r_texture_blanknormalmap;
9052 t->glosstexture = r_texture_black;
9053 t->glowtexture = NULL;
9054 t->fogtexture = NULL;
9055 t->reflectmasktexture = NULL;
9056 t->backgroundbasetexture = NULL;
9057 t->backgroundnmaptexture = r_texture_blanknormalmap;
9058 t->backgroundglosstexture = r_texture_black;
9059 t->backgroundglowtexture = NULL;
9060 t->specularscale = 0;
9061 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9064 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9065 VectorClear(t->dlightcolor);
9066 t->currentnumlayers = 0;
9067 if (t->currentmaterialflags & MATERIALFLAG_WALL)
9069 int blendfunc1, blendfunc2;
9071 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9073 blendfunc1 = GL_SRC_ALPHA;
9074 blendfunc2 = GL_ONE;
9076 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9078 blendfunc1 = GL_SRC_ALPHA;
9079 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9081 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9083 blendfunc1 = t->customblendfunc[0];
9084 blendfunc2 = t->customblendfunc[1];
9088 blendfunc1 = GL_ONE;
9089 blendfunc2 = GL_ZERO;
9091 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9092 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9094 // fullbright is not affected by r_refdef.lightmapintensity
9095 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]);
9096 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9097 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]);
9098 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9099 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]);
9103 vec3_t ambientcolor;
9105 // set the color tint used for lights affecting this surface
9106 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9108 // q3bsp has no lightmap updates, so the lightstylevalue that
9109 // would normally be baked into the lightmap must be
9110 // applied to the color
9111 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9112 if (model->type == mod_brushq3)
9113 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9114 colorscale *= r_refdef.lightmapintensity;
9115 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9116 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9117 // basic lit geometry
9118 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]);
9119 // add pants/shirt if needed
9120 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9121 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]);
9122 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9123 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]);
9124 // now add ambient passes if needed
9125 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9127 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]);
9128 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9129 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]);
9130 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9131 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]);
9134 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9135 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]);
9136 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9138 // if this is opaque use alpha blend which will darken the earlier
9141 // if this is an alpha blended material, all the earlier passes
9142 // were darkened by fog already, so we only need to add the fog
9143 // color ontop through the fog mask texture
9145 // if this is an additive blended material, all the earlier passes
9146 // were darkened by fog already, and we should not add fog color
9147 // (because the background was not darkened, there is no fog color
9148 // that was lost behind it).
9149 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]);
9153 return t->currentframe;
9156 rsurfacestate_t rsurface;
9158 void R_Mesh_ResizeArrays(int newvertices)
9161 if (rsurface.array_size >= newvertices)
9163 if (rsurface.array_modelvertex3f)
9164 Mem_Free(rsurface.array_modelvertex3f);
9165 rsurface.array_size = (newvertices + 1023) & ~1023;
9166 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9167 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
9168 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
9169 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
9170 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
9171 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
9172 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9173 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9174 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
9175 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
9176 rsurface.array_color4f = base + rsurface.array_size * 27;
9177 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9180 void RSurf_ActiveWorldEntity(void)
9182 dp_model_t *model = r_refdef.scene.worldmodel;
9183 //if (rsurface.entity == r_refdef.scene.worldentity)
9185 rsurface.entity = r_refdef.scene.worldentity;
9186 rsurface.skeleton = NULL;
9187 rsurface.ent_skinnum = 0;
9188 rsurface.ent_qwskin = -1;
9189 rsurface.ent_shadertime = 0;
9190 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9191 if (rsurface.array_size < model->surfmesh.num_vertices)
9192 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9193 rsurface.matrix = identitymatrix;
9194 rsurface.inversematrix = identitymatrix;
9195 rsurface.matrixscale = 1;
9196 rsurface.inversematrixscale = 1;
9197 R_EntityMatrix(&identitymatrix);
9198 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9199 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9200 rsurface.fograngerecip = r_refdef.fograngerecip;
9201 rsurface.fogheightfade = r_refdef.fogheightfade;
9202 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9203 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9204 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9205 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9206 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9207 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9208 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9209 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9210 rsurface.colormod[3] = 1;
9211 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);
9212 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9213 rsurface.frameblend[0].lerp = 1;
9214 rsurface.ent_alttextures = false;
9215 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9216 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9217 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9218 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9219 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9220 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9221 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9222 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9223 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9224 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9225 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9226 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9227 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9228 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9229 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9230 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9231 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9232 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9233 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9234 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9235 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9236 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9237 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9238 rsurface.modelelement3i = model->surfmesh.data_element3i;
9239 rsurface.modelelement3s = model->surfmesh.data_element3s;
9240 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9241 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9242 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9243 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9244 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9245 rsurface.modelsurfaces = model->data_surfaces;
9246 rsurface.generatedvertex = false;
9247 rsurface.vertex3f = rsurface.modelvertex3f;
9248 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9249 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9250 rsurface.svector3f = rsurface.modelsvector3f;
9251 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9252 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9253 rsurface.tvector3f = rsurface.modeltvector3f;
9254 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9255 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9256 rsurface.normal3f = rsurface.modelnormal3f;
9257 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9258 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9259 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9262 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9264 dp_model_t *model = ent->model;
9265 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9267 rsurface.entity = (entity_render_t *)ent;
9268 rsurface.skeleton = ent->skeleton;
9269 rsurface.ent_skinnum = ent->skinnum;
9270 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;
9271 rsurface.ent_shadertime = ent->shadertime;
9272 rsurface.ent_flags = ent->flags;
9273 if (rsurface.array_size < model->surfmesh.num_vertices)
9274 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9275 rsurface.matrix = ent->matrix;
9276 rsurface.inversematrix = ent->inversematrix;
9277 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9278 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9279 R_EntityMatrix(&rsurface.matrix);
9280 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9281 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9282 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9283 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9284 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9285 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9286 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9287 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9288 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9289 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9290 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9291 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9292 rsurface.colormod[3] = ent->alpha;
9293 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9294 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9295 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9296 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9297 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9298 if (ent->model->brush.submodel && !prepass)
9300 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9301 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9303 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9305 if (ent->animcache_vertex3f && !r_framedata_failed)
9307 rsurface.modelvertex3f = ent->animcache_vertex3f;
9308 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9309 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9310 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9312 else if (wanttangents)
9314 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9315 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9316 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9317 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9318 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9320 else if (wantnormals)
9322 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9323 rsurface.modelsvector3f = NULL;
9324 rsurface.modeltvector3f = NULL;
9325 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9326 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9330 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9331 rsurface.modelsvector3f = NULL;
9332 rsurface.modeltvector3f = NULL;
9333 rsurface.modelnormal3f = NULL;
9334 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9336 rsurface.modelvertex3f_bufferobject = 0;
9337 rsurface.modelvertex3f_bufferoffset = 0;
9338 rsurface.modelsvector3f_bufferobject = 0;
9339 rsurface.modelsvector3f_bufferoffset = 0;
9340 rsurface.modeltvector3f_bufferobject = 0;
9341 rsurface.modeltvector3f_bufferoffset = 0;
9342 rsurface.modelnormal3f_bufferobject = 0;
9343 rsurface.modelnormal3f_bufferoffset = 0;
9344 rsurface.generatedvertex = true;
9348 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9349 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9350 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9351 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9352 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9353 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9354 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9355 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9356 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9357 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9358 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9359 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9360 rsurface.generatedvertex = false;
9362 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9363 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9364 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9365 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9366 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9367 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9368 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9369 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9370 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9371 rsurface.modelelement3i = model->surfmesh.data_element3i;
9372 rsurface.modelelement3s = model->surfmesh.data_element3s;
9373 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9374 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9375 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9376 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9377 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9378 rsurface.modelsurfaces = model->data_surfaces;
9379 rsurface.vertex3f = rsurface.modelvertex3f;
9380 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9381 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9382 rsurface.svector3f = rsurface.modelsvector3f;
9383 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9384 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9385 rsurface.tvector3f = rsurface.modeltvector3f;
9386 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9387 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9388 rsurface.normal3f = rsurface.modelnormal3f;
9389 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9390 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9391 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9394 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)
9396 rsurface.entity = r_refdef.scene.worldentity;
9397 rsurface.skeleton = NULL;
9398 rsurface.ent_skinnum = 0;
9399 rsurface.ent_qwskin = -1;
9400 rsurface.ent_shadertime = shadertime;
9401 rsurface.ent_flags = entflags;
9402 rsurface.modelnum_vertices = numvertices;
9403 rsurface.modelnum_triangles = numtriangles;
9404 if (rsurface.array_size < rsurface.modelnum_vertices)
9405 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9406 rsurface.matrix = *matrix;
9407 rsurface.inversematrix = *inversematrix;
9408 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9409 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9410 R_EntityMatrix(&rsurface.matrix);
9411 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9412 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9413 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9414 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9415 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9416 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9417 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9418 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9419 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9420 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9421 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9422 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9423 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);
9424 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9425 rsurface.frameblend[0].lerp = 1;
9426 rsurface.ent_alttextures = false;
9427 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9428 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9431 rsurface.modelvertex3f = vertex3f;
9432 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9433 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9434 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9436 else if (wantnormals)
9438 rsurface.modelvertex3f = vertex3f;
9439 rsurface.modelsvector3f = NULL;
9440 rsurface.modeltvector3f = NULL;
9441 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9445 rsurface.modelvertex3f = vertex3f;
9446 rsurface.modelsvector3f = NULL;
9447 rsurface.modeltvector3f = NULL;
9448 rsurface.modelnormal3f = NULL;
9450 rsurface.modelvertex3f_bufferobject = 0;
9451 rsurface.modelvertex3f_bufferoffset = 0;
9452 rsurface.modelsvector3f_bufferobject = 0;
9453 rsurface.modelsvector3f_bufferoffset = 0;
9454 rsurface.modeltvector3f_bufferobject = 0;
9455 rsurface.modeltvector3f_bufferoffset = 0;
9456 rsurface.modelnormal3f_bufferobject = 0;
9457 rsurface.modelnormal3f_bufferoffset = 0;
9458 rsurface.generatedvertex = true;
9459 rsurface.modellightmapcolor4f = color4f;
9460 rsurface.modellightmapcolor4f_bufferobject = 0;
9461 rsurface.modellightmapcolor4f_bufferoffset = 0;
9462 rsurface.modeltexcoordtexture2f = texcoord2f;
9463 rsurface.modeltexcoordtexture2f_bufferobject = 0;
9464 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9465 rsurface.modeltexcoordlightmap2f = NULL;
9466 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9467 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9468 rsurface.modelelement3i = element3i;
9469 rsurface.modelelement3s = element3s;
9470 rsurface.modelelement3i_bufferobject = 0;
9471 rsurface.modelelement3s_bufferobject = 0;
9472 rsurface.modellightmapoffsets = NULL;
9473 rsurface.modelsurfaces = NULL;
9474 rsurface.vertex3f = rsurface.modelvertex3f;
9475 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9476 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9477 rsurface.svector3f = rsurface.modelsvector3f;
9478 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9479 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9480 rsurface.tvector3f = rsurface.modeltvector3f;
9481 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9482 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9483 rsurface.normal3f = rsurface.modelnormal3f;
9484 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9485 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9486 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9488 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9490 if ((wantnormals || wanttangents) && !normal3f)
9491 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9492 if (wanttangents && !svector3f)
9493 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);
9497 float RSurf_FogPoint(const float *v)
9499 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9500 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9501 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9502 float FogHeightFade = r_refdef.fogheightfade;
9504 unsigned int fogmasktableindex;
9505 if (r_refdef.fogplaneviewabove)
9506 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9508 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9509 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9510 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9513 float RSurf_FogVertex(const float *v)
9515 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9516 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9517 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9518 float FogHeightFade = rsurface.fogheightfade;
9520 unsigned int fogmasktableindex;
9521 if (r_refdef.fogplaneviewabove)
9522 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9524 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9525 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9526 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9529 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9530 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9533 int texturesurfaceindex;
9538 const float *v1, *in_tc;
9540 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9542 q3shaderinfo_deform_t *deform;
9543 // 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
9544 if (rsurface.generatedvertex)
9546 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9547 generatenormals = true;
9548 for (i = 0;i < Q3MAXDEFORMS;i++)
9550 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9552 generatetangents = true;
9553 generatenormals = true;
9555 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9556 generatenormals = true;
9558 if (generatenormals && !rsurface.modelnormal3f)
9560 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9561 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9562 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9563 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9565 if (generatetangents && !rsurface.modelsvector3f)
9567 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9568 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9569 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9570 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9571 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9572 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9573 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);
9576 rsurface.vertex3f = rsurface.modelvertex3f;
9577 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9578 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9579 rsurface.svector3f = rsurface.modelsvector3f;
9580 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9581 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9582 rsurface.tvector3f = rsurface.modeltvector3f;
9583 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9584 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9585 rsurface.normal3f = rsurface.modelnormal3f;
9586 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9587 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9588 // if vertices are deformed (sprite flares and things in maps, possibly
9589 // water waves, bulges and other deformations), generate them into
9590 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9591 // (may be static model data or generated data for an animated model, or
9592 // the previous deform pass)
9593 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9595 switch (deform->deform)
9598 case Q3DEFORM_PROJECTIONSHADOW:
9599 case Q3DEFORM_TEXT0:
9600 case Q3DEFORM_TEXT1:
9601 case Q3DEFORM_TEXT2:
9602 case Q3DEFORM_TEXT3:
9603 case Q3DEFORM_TEXT4:
9604 case Q3DEFORM_TEXT5:
9605 case Q3DEFORM_TEXT6:
9606 case Q3DEFORM_TEXT7:
9609 case Q3DEFORM_AUTOSPRITE:
9610 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9611 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9612 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9613 VectorNormalize(newforward);
9614 VectorNormalize(newright);
9615 VectorNormalize(newup);
9616 // make deformed versions of only the model vertices used by the specified surfaces
9617 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9619 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9620 // a single autosprite surface can contain multiple sprites...
9621 for (j = 0;j < surface->num_vertices - 3;j += 4)
9623 VectorClear(center);
9624 for (i = 0;i < 4;i++)
9625 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9626 VectorScale(center, 0.25f, center);
9627 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9628 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9629 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9630 for (i = 0;i < 4;i++)
9632 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9633 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9636 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);
9637 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);
9639 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9640 rsurface.vertex3f_bufferobject = 0;
9641 rsurface.vertex3f_bufferoffset = 0;
9642 rsurface.svector3f = rsurface.array_deformedsvector3f;
9643 rsurface.svector3f_bufferobject = 0;
9644 rsurface.svector3f_bufferoffset = 0;
9645 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9646 rsurface.tvector3f_bufferobject = 0;
9647 rsurface.tvector3f_bufferoffset = 0;
9648 rsurface.normal3f = rsurface.array_deformednormal3f;
9649 rsurface.normal3f_bufferobject = 0;
9650 rsurface.normal3f_bufferoffset = 0;
9652 case Q3DEFORM_AUTOSPRITE2:
9653 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9654 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9655 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9656 VectorNormalize(newforward);
9657 VectorNormalize(newright);
9658 VectorNormalize(newup);
9659 // make deformed versions of only the model vertices used by the specified surfaces
9660 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9662 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9663 const float *v1, *v2;
9673 memset(shortest, 0, sizeof(shortest));
9674 // a single autosprite surface can contain multiple sprites...
9675 for (j = 0;j < surface->num_vertices - 3;j += 4)
9677 VectorClear(center);
9678 for (i = 0;i < 4;i++)
9679 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9680 VectorScale(center, 0.25f, center);
9681 // find the two shortest edges, then use them to define the
9682 // axis vectors for rotating around the central axis
9683 for (i = 0;i < 6;i++)
9685 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9686 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9688 Debug_PolygonBegin(NULL, 0);
9689 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9690 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);
9691 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9694 l = VectorDistance2(v1, v2);
9695 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9697 l += (1.0f / 1024.0f);
9698 if (shortest[0].length2 > l || i == 0)
9700 shortest[1] = shortest[0];
9701 shortest[0].length2 = l;
9702 shortest[0].v1 = v1;
9703 shortest[0].v2 = v2;
9705 else if (shortest[1].length2 > l || i == 1)
9707 shortest[1].length2 = l;
9708 shortest[1].v1 = v1;
9709 shortest[1].v2 = v2;
9712 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9713 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9715 Debug_PolygonBegin(NULL, 0);
9716 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9717 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);
9718 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9721 // this calculates the right vector from the shortest edge
9722 // and the up vector from the edge midpoints
9723 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9724 VectorNormalize(right);
9725 VectorSubtract(end, start, up);
9726 VectorNormalize(up);
9727 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9728 VectorSubtract(rsurface.localvieworigin, center, forward);
9729 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9730 VectorNegate(forward, forward);
9731 VectorReflect(forward, 0, up, forward);
9732 VectorNormalize(forward);
9733 CrossProduct(up, forward, newright);
9734 VectorNormalize(newright);
9736 Debug_PolygonBegin(NULL, 0);
9737 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);
9738 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9739 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9743 Debug_PolygonBegin(NULL, 0);
9744 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9745 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9746 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9749 // rotate the quad around the up axis vector, this is made
9750 // especially easy by the fact we know the quad is flat,
9751 // so we only have to subtract the center position and
9752 // measure distance along the right vector, and then
9753 // multiply that by the newright vector and add back the
9755 // we also need to subtract the old position to undo the
9756 // displacement from the center, which we do with a
9757 // DotProduct, the subtraction/addition of center is also
9758 // optimized into DotProducts here
9759 l = DotProduct(right, center);
9760 for (i = 0;i < 4;i++)
9762 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9763 f = DotProduct(right, v1) - l;
9764 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9767 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);
9768 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);
9770 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9771 rsurface.vertex3f_bufferobject = 0;
9772 rsurface.vertex3f_bufferoffset = 0;
9773 rsurface.svector3f = rsurface.array_deformedsvector3f;
9774 rsurface.svector3f_bufferobject = 0;
9775 rsurface.svector3f_bufferoffset = 0;
9776 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9777 rsurface.tvector3f_bufferobject = 0;
9778 rsurface.tvector3f_bufferoffset = 0;
9779 rsurface.normal3f = rsurface.array_deformednormal3f;
9780 rsurface.normal3f_bufferobject = 0;
9781 rsurface.normal3f_bufferoffset = 0;
9783 case Q3DEFORM_NORMAL:
9784 // deform the normals to make reflections wavey
9785 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9787 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9788 for (j = 0;j < surface->num_vertices;j++)
9791 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9792 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9793 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9794 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9795 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9796 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9797 VectorNormalize(normal);
9799 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);
9801 rsurface.svector3f = rsurface.array_deformedsvector3f;
9802 rsurface.svector3f_bufferobject = 0;
9803 rsurface.svector3f_bufferoffset = 0;
9804 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9805 rsurface.tvector3f_bufferobject = 0;
9806 rsurface.tvector3f_bufferoffset = 0;
9807 rsurface.normal3f = rsurface.array_deformednormal3f;
9808 rsurface.normal3f_bufferobject = 0;
9809 rsurface.normal3f_bufferoffset = 0;
9812 // deform vertex array to make wavey water and flags and such
9813 waveparms[0] = deform->waveparms[0];
9814 waveparms[1] = deform->waveparms[1];
9815 waveparms[2] = deform->waveparms[2];
9816 waveparms[3] = deform->waveparms[3];
9817 // this is how a divisor of vertex influence on deformation
9818 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9819 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9820 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9822 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9823 for (j = 0;j < surface->num_vertices;j++)
9825 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9826 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9827 // if the wavefunc depends on time, evaluate it per-vertex
9830 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9831 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9833 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9836 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9837 rsurface.vertex3f_bufferobject = 0;
9838 rsurface.vertex3f_bufferoffset = 0;
9840 case Q3DEFORM_BULGE:
9841 // deform vertex array to make the surface have moving bulges
9842 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9844 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9845 for (j = 0;j < surface->num_vertices;j++)
9847 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9848 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9851 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9852 rsurface.vertex3f_bufferobject = 0;
9853 rsurface.vertex3f_bufferoffset = 0;
9856 // deform vertex array
9857 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9858 VectorScale(deform->parms, scale, waveparms);
9859 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9861 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9862 for (j = 0;j < surface->num_vertices;j++)
9863 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9865 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9866 rsurface.vertex3f_bufferobject = 0;
9867 rsurface.vertex3f_bufferoffset = 0;
9871 // generate texcoords based on the chosen texcoord source
9872 switch(rsurface.texture->tcgen.tcgen)
9875 case Q3TCGEN_TEXTURE:
9876 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9877 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
9878 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9880 case Q3TCGEN_LIGHTMAP:
9881 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
9882 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9883 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9885 case Q3TCGEN_VECTOR:
9886 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9888 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9889 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)
9891 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9892 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9895 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9896 rsurface.texcoordtexture2f_bufferobject = 0;
9897 rsurface.texcoordtexture2f_bufferoffset = 0;
9899 case Q3TCGEN_ENVIRONMENT:
9900 // make environment reflections using a spheremap
9901 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9903 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9904 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9905 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9906 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9907 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9909 // identical to Q3A's method, but executed in worldspace so
9910 // carried models can be shiny too
9912 float viewer[3], d, reflected[3], worldreflected[3];
9914 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9915 // VectorNormalize(viewer);
9917 d = DotProduct(normal, viewer);
9919 reflected[0] = normal[0]*2*d - viewer[0];
9920 reflected[1] = normal[1]*2*d - viewer[1];
9921 reflected[2] = normal[2]*2*d - viewer[2];
9922 // note: this is proportinal to viewer, so we can normalize later
9924 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9925 VectorNormalize(worldreflected);
9927 // note: this sphere map only uses world x and z!
9928 // so positive and negative y will LOOK THE SAME.
9929 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9930 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9933 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9934 rsurface.texcoordtexture2f_bufferobject = 0;
9935 rsurface.texcoordtexture2f_bufferoffset = 0;
9938 // the only tcmod that needs software vertex processing is turbulent, so
9939 // check for it here and apply the changes if needed
9940 // and we only support that as the first one
9941 // (handling a mixture of turbulent and other tcmods would be problematic
9942 // without punting it entirely to a software path)
9943 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9945 amplitude = rsurface.texture->tcmods[0].parms[1];
9946 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9947 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9949 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9950 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)
9952 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9953 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9956 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9957 rsurface.texcoordtexture2f_bufferobject = 0;
9958 rsurface.texcoordtexture2f_bufferoffset = 0;
9960 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9961 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9962 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9963 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9966 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9969 const msurface_t *surface = texturesurfacelist[0];
9970 const msurface_t *surface2;
9975 // TODO: lock all array ranges before render, rather than on each surface
9976 if (texturenumsurfaces == 1)
9977 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);
9978 else if (r_batchmode.integer == 2)
9980 #define MAXBATCHTRIANGLES 4096
9981 int batchtriangles = 0;
9982 static int batchelements[MAXBATCHTRIANGLES*3];
9983 for (i = 0;i < texturenumsurfaces;i = j)
9985 surface = texturesurfacelist[i];
9987 if (surface->num_triangles > MAXBATCHTRIANGLES)
9989 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);
9992 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9993 batchtriangles = surface->num_triangles;
9994 firstvertex = surface->num_firstvertex;
9995 endvertex = surface->num_firstvertex + surface->num_vertices;
9996 for (;j < texturenumsurfaces;j++)
9998 surface2 = texturesurfacelist[j];
9999 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10001 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10002 batchtriangles += surface2->num_triangles;
10003 firstvertex = min(firstvertex, surface2->num_firstvertex);
10004 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10006 surface2 = texturesurfacelist[j-1];
10007 numvertices = endvertex - firstvertex;
10008 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10011 else if (r_batchmode.integer == 1)
10013 for (i = 0;i < texturenumsurfaces;i = j)
10015 surface = texturesurfacelist[i];
10016 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10017 if (texturesurfacelist[j] != surface2)
10019 surface2 = texturesurfacelist[j-1];
10020 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10021 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10022 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10027 for (i = 0;i < texturenumsurfaces;i++)
10029 surface = texturesurfacelist[i];
10030 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);
10035 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10037 switch(vid.renderpath)
10039 case RENDERPATH_CGGL:
10041 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10042 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10045 case RENDERPATH_GL20:
10046 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10047 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10049 case RENDERPATH_GL13:
10050 case RENDERPATH_GL11:
10051 R_Mesh_TexBind(0, surface->lightmaptexture);
10056 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10058 // pick the closest matching water plane and bind textures
10059 int planeindex, vertexindex;
10063 r_waterstate_waterplane_t *p, *bestp;
10066 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10069 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10071 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10072 d += fabs(PlaneDiff(vert, &p->plane));
10074 if (bestd > d || !bestp)
10080 switch(vid.renderpath)
10082 case RENDERPATH_CGGL:
10084 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10085 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10088 case RENDERPATH_GL20:
10089 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10090 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10092 case RENDERPATH_GL13:
10093 case RENDERPATH_GL11:
10098 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10101 const msurface_t *surface;
10102 if (r_waterstate.renderingscene)
10104 for (i = 0;i < texturenumsurfaces;i++)
10106 surface = texturesurfacelist[i];
10107 RSurf_BindLightmapForSurface(surface);
10108 RSurf_BindReflectionForSurface(surface);
10109 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);
10113 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10117 const msurface_t *surface = texturesurfacelist[0];
10118 const msurface_t *surface2;
10123 if (texturenumsurfaces == 1)
10125 RSurf_BindLightmapForSurface(surface);
10126 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);
10128 else if (r_batchmode.integer == 2)
10130 #define MAXBATCHTRIANGLES 4096
10131 int batchtriangles = 0;
10132 static int batchelements[MAXBATCHTRIANGLES*3];
10133 for (i = 0;i < texturenumsurfaces;i = j)
10135 surface = texturesurfacelist[i];
10136 RSurf_BindLightmapForSurface(surface);
10138 if (surface->num_triangles > MAXBATCHTRIANGLES)
10140 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);
10143 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10144 batchtriangles = surface->num_triangles;
10145 firstvertex = surface->num_firstvertex;
10146 endvertex = surface->num_firstvertex + surface->num_vertices;
10147 for (;j < texturenumsurfaces;j++)
10149 surface2 = texturesurfacelist[j];
10150 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10152 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10153 batchtriangles += surface2->num_triangles;
10154 firstvertex = min(firstvertex, surface2->num_firstvertex);
10155 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10157 surface2 = texturesurfacelist[j-1];
10158 numvertices = endvertex - firstvertex;
10159 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10162 else if (r_batchmode.integer == 1)
10165 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10166 for (i = 0;i < texturenumsurfaces;i = j)
10168 surface = texturesurfacelist[i];
10169 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10170 if (texturesurfacelist[j] != surface2)
10172 Con_Printf(" %i", j - i);
10175 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10177 for (i = 0;i < texturenumsurfaces;i = j)
10179 surface = texturesurfacelist[i];
10180 RSurf_BindLightmapForSurface(surface);
10181 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10182 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10185 Con_Printf(" %i", j - i);
10187 surface2 = texturesurfacelist[j-1];
10188 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10189 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10190 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10198 for (i = 0;i < texturenumsurfaces;i++)
10200 surface = texturesurfacelist[i];
10201 RSurf_BindLightmapForSurface(surface);
10202 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);
10207 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10210 int texturesurfaceindex;
10211 if (r_showsurfaces.integer == 2)
10213 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10215 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10216 for (j = 0;j < surface->num_triangles;j++)
10218 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10219 GL_Color(f, f, f, 1);
10220 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10226 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10228 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10229 int k = (int)(((size_t)surface) / sizeof(msurface_t));
10230 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);
10231 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);
10236 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10238 int texturesurfaceindex;
10242 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10244 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10245 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)
10253 rsurface.lightmapcolor4f = rsurface.array_color4f;
10254 rsurface.lightmapcolor4f_bufferobject = 0;
10255 rsurface.lightmapcolor4f_bufferoffset = 0;
10258 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10260 int texturesurfaceindex;
10266 if (rsurface.lightmapcolor4f)
10268 // generate color arrays for the surfaces in this list
10269 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10271 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10272 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)
10274 f = RSurf_FogVertex(v);
10284 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10286 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10287 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)
10289 f = RSurf_FogVertex(v);
10297 rsurface.lightmapcolor4f = rsurface.array_color4f;
10298 rsurface.lightmapcolor4f_bufferobject = 0;
10299 rsurface.lightmapcolor4f_bufferoffset = 0;
10302 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10304 int texturesurfaceindex;
10310 if (!rsurface.lightmapcolor4f)
10312 // generate color arrays for the surfaces in this list
10313 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10315 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10316 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)
10318 f = RSurf_FogVertex(v);
10319 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10320 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10321 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10325 rsurface.lightmapcolor4f = rsurface.array_color4f;
10326 rsurface.lightmapcolor4f_bufferobject = 0;
10327 rsurface.lightmapcolor4f_bufferoffset = 0;
10330 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10332 int texturesurfaceindex;
10336 if (!rsurface.lightmapcolor4f)
10338 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10340 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10341 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)
10349 rsurface.lightmapcolor4f = rsurface.array_color4f;
10350 rsurface.lightmapcolor4f_bufferobject = 0;
10351 rsurface.lightmapcolor4f_bufferoffset = 0;
10354 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10356 int texturesurfaceindex;
10360 if (!rsurface.lightmapcolor4f)
10362 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10364 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10365 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)
10367 c2[0] = c[0] + r_refdef.scene.ambient;
10368 c2[1] = c[1] + r_refdef.scene.ambient;
10369 c2[2] = c[2] + r_refdef.scene.ambient;
10373 rsurface.lightmapcolor4f = rsurface.array_color4f;
10374 rsurface.lightmapcolor4f_bufferobject = 0;
10375 rsurface.lightmapcolor4f_bufferoffset = 0;
10378 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10381 rsurface.lightmapcolor4f = NULL;
10382 rsurface.lightmapcolor4f_bufferobject = 0;
10383 rsurface.lightmapcolor4f_bufferoffset = 0;
10384 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10385 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10386 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10387 GL_Color(r, g, b, a);
10388 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10391 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10393 // TODO: optimize applyfog && applycolor case
10394 // just apply fog if necessary, and tint the fog color array if necessary
10395 rsurface.lightmapcolor4f = NULL;
10396 rsurface.lightmapcolor4f_bufferobject = 0;
10397 rsurface.lightmapcolor4f_bufferoffset = 0;
10398 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10399 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10400 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10401 GL_Color(r, g, b, a);
10402 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10405 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10407 int texturesurfaceindex;
10411 if (texturesurfacelist[0]->lightmapinfo)
10413 // generate color arrays for the surfaces in this list
10414 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10416 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10417 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10419 if (surface->lightmapinfo->samples)
10421 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10422 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10423 VectorScale(lm, scale, c);
10424 if (surface->lightmapinfo->styles[1] != 255)
10426 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10428 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10429 VectorMA(c, scale, lm, c);
10430 if (surface->lightmapinfo->styles[2] != 255)
10433 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10434 VectorMA(c, scale, lm, c);
10435 if (surface->lightmapinfo->styles[3] != 255)
10438 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10439 VectorMA(c, scale, lm, c);
10449 rsurface.lightmapcolor4f = rsurface.array_color4f;
10450 rsurface.lightmapcolor4f_bufferobject = 0;
10451 rsurface.lightmapcolor4f_bufferoffset = 0;
10455 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10456 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10457 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10459 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10460 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10461 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10462 GL_Color(r, g, b, a);
10463 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10466 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10468 int texturesurfaceindex;
10475 vec3_t ambientcolor;
10476 vec3_t diffusecolor;
10480 VectorCopy(rsurface.modellight_lightdir, lightdir);
10481 f = 0.5f * r_refdef.lightmapintensity;
10482 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10483 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10484 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10485 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10486 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10487 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10489 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10491 // generate color arrays for the surfaces in this list
10492 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10494 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10495 int numverts = surface->num_vertices;
10496 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10497 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10498 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10499 // q3-style directional shading
10500 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10502 if ((f = DotProduct(n, lightdir)) > 0)
10503 VectorMA(ambientcolor, f, diffusecolor, c);
10505 VectorCopy(ambientcolor, c);
10513 rsurface.lightmapcolor4f = rsurface.array_color4f;
10514 rsurface.lightmapcolor4f_bufferobject = 0;
10515 rsurface.lightmapcolor4f_bufferoffset = 0;
10516 *applycolor = false;
10520 *r = ambientcolor[0];
10521 *g = ambientcolor[1];
10522 *b = ambientcolor[2];
10523 rsurface.lightmapcolor4f = NULL;
10524 rsurface.lightmapcolor4f_bufferobject = 0;
10525 rsurface.lightmapcolor4f_bufferoffset = 0;
10529 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10531 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10532 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10533 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10534 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10535 GL_Color(r, g, b, a);
10536 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10539 void RSurf_SetupDepthAndCulling(void)
10541 // submodels are biased to avoid z-fighting with world surfaces that they
10542 // may be exactly overlapping (avoids z-fighting artifacts on certain
10543 // doors and things in Quake maps)
10544 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10545 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10546 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10547 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10550 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10552 // transparent sky would be ridiculous
10553 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10555 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10556 skyrenderlater = true;
10557 RSurf_SetupDepthAndCulling();
10558 GL_DepthMask(true);
10559 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10560 // skymasking on them, and Quake3 never did sky masking (unlike
10561 // software Quake and software Quake2), so disable the sky masking
10562 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10563 // and skymasking also looks very bad when noclipping outside the
10564 // level, so don't use it then either.
10565 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10567 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10568 R_Mesh_ColorPointer(NULL, 0, 0);
10569 R_Mesh_ResetTextureState();
10570 if (skyrendermasked)
10572 R_SetupShader_DepthOrShadow();
10573 // depth-only (masking)
10574 GL_ColorMask(0,0,0,0);
10575 // just to make sure that braindead drivers don't draw
10576 // anything despite that colormask...
10577 GL_BlendFunc(GL_ZERO, GL_ONE);
10581 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10583 GL_BlendFunc(GL_ONE, GL_ZERO);
10585 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10586 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10587 if (skyrendermasked)
10588 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10590 R_Mesh_ResetTextureState();
10591 GL_Color(1, 1, 1, 1);
10594 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10595 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10596 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10598 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10600 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10603 // render screenspace normalmap to texture
10604 GL_DepthMask(true);
10605 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10606 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10608 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10610 // render water or distortion background, then blend surface on top
10611 GL_DepthMask(true);
10612 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10613 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10614 GL_DepthMask(false);
10615 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10616 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10617 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10619 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10623 // render surface normally
10624 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10625 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10626 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10627 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10628 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10629 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10631 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10635 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10637 // OpenGL 1.3 path - anything not completely ancient
10638 int texturesurfaceindex;
10639 qboolean applycolor;
10642 const texturelayer_t *layer;
10643 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10645 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10648 int layertexrgbscale;
10649 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10651 if (layerindex == 0)
10652 GL_AlphaTest(true);
10655 GL_AlphaTest(false);
10656 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10659 GL_DepthMask(layer->depthmask && writedepth);
10660 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10661 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10663 layertexrgbscale = 4;
10664 VectorScale(layer->color, 0.25f, layercolor);
10666 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10668 layertexrgbscale = 2;
10669 VectorScale(layer->color, 0.5f, layercolor);
10673 layertexrgbscale = 1;
10674 VectorScale(layer->color, 1.0f, layercolor);
10676 layercolor[3] = layer->color[3];
10677 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10678 R_Mesh_ColorPointer(NULL, 0, 0);
10679 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10680 switch (layer->type)
10682 case TEXTURELAYERTYPE_LITTEXTURE:
10683 // single-pass lightmapped texture with 2x rgbscale
10684 R_Mesh_TexBind(0, r_texture_white);
10685 R_Mesh_TexMatrix(0, NULL);
10686 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10687 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10688 R_Mesh_TexBind(1, layer->texture);
10689 R_Mesh_TexMatrix(1, &layer->texmatrix);
10690 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10691 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10692 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10693 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10694 else if (rsurface.uselightmaptexture)
10695 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10697 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10699 case TEXTURELAYERTYPE_TEXTURE:
10700 // singletexture unlit texture with transparency support
10701 R_Mesh_TexBind(0, layer->texture);
10702 R_Mesh_TexMatrix(0, &layer->texmatrix);
10703 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10704 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10705 R_Mesh_TexBind(1, 0);
10706 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10707 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10709 case TEXTURELAYERTYPE_FOG:
10710 // singletexture fogging
10711 if (layer->texture)
10713 R_Mesh_TexBind(0, layer->texture);
10714 R_Mesh_TexMatrix(0, &layer->texmatrix);
10715 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10716 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10720 R_Mesh_TexBind(0, 0);
10721 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10723 R_Mesh_TexBind(1, 0);
10724 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10725 // generate a color array for the fog pass
10726 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10727 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10733 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10734 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)
10736 f = 1 - RSurf_FogVertex(v);
10737 c[0] = layercolor[0];
10738 c[1] = layercolor[1];
10739 c[2] = layercolor[2];
10740 c[3] = f * layercolor[3];
10743 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10746 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10750 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10752 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10753 GL_AlphaTest(false);
10757 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10759 // OpenGL 1.1 - crusty old voodoo path
10760 int texturesurfaceindex;
10763 const texturelayer_t *layer;
10764 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10766 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10768 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10770 if (layerindex == 0)
10771 GL_AlphaTest(true);
10774 GL_AlphaTest(false);
10775 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10778 GL_DepthMask(layer->depthmask && writedepth);
10779 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10780 R_Mesh_ColorPointer(NULL, 0, 0);
10781 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10782 switch (layer->type)
10784 case TEXTURELAYERTYPE_LITTEXTURE:
10785 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10787 // two-pass lit texture with 2x rgbscale
10788 // first the lightmap pass
10789 R_Mesh_TexBind(0, r_texture_white);
10790 R_Mesh_TexMatrix(0, NULL);
10791 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10792 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10793 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10794 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10795 else if (rsurface.uselightmaptexture)
10796 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10798 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10799 // then apply the texture to it
10800 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10801 R_Mesh_TexBind(0, layer->texture);
10802 R_Mesh_TexMatrix(0, &layer->texmatrix);
10803 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10804 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10805 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);
10809 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10810 R_Mesh_TexBind(0, layer->texture);
10811 R_Mesh_TexMatrix(0, &layer->texmatrix);
10812 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10813 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10814 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10815 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);
10817 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);
10820 case TEXTURELAYERTYPE_TEXTURE:
10821 // singletexture unlit texture with transparency support
10822 R_Mesh_TexBind(0, layer->texture);
10823 R_Mesh_TexMatrix(0, &layer->texmatrix);
10824 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10825 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10826 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);
10828 case TEXTURELAYERTYPE_FOG:
10829 // singletexture fogging
10830 if (layer->texture)
10832 R_Mesh_TexBind(0, layer->texture);
10833 R_Mesh_TexMatrix(0, &layer->texmatrix);
10834 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10835 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10839 R_Mesh_TexBind(0, 0);
10840 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10842 // generate a color array for the fog pass
10843 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10844 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10850 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10851 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)
10853 f = 1 - RSurf_FogVertex(v);
10854 c[0] = layer->color[0];
10855 c[1] = layer->color[1];
10856 c[2] = layer->color[2];
10857 c[3] = f * layer->color[3];
10860 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10863 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10867 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10869 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10870 GL_AlphaTest(false);
10874 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10878 GL_AlphaTest(false);
10879 R_Mesh_ColorPointer(NULL, 0, 0);
10880 R_Mesh_ResetTextureState();
10881 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10883 if(rsurface.texture && rsurface.texture->currentskinframe)
10885 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10886 c[3] *= rsurface.texture->currentalpha;
10896 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10898 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10899 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10900 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10903 // brighten it up (as texture value 127 means "unlit")
10904 c[0] *= 2 * r_refdef.view.colorscale;
10905 c[1] *= 2 * r_refdef.view.colorscale;
10906 c[2] *= 2 * r_refdef.view.colorscale;
10908 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10909 c[3] *= r_wateralpha.value;
10911 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10913 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10914 GL_DepthMask(false);
10916 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10918 GL_BlendFunc(GL_ONE, GL_ONE);
10919 GL_DepthMask(false);
10921 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10923 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10924 GL_DepthMask(false);
10926 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10928 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10929 GL_DepthMask(false);
10933 GL_BlendFunc(GL_ONE, GL_ZERO);
10934 GL_DepthMask(writedepth);
10937 rsurface.lightmapcolor4f = NULL;
10939 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10941 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10943 rsurface.lightmapcolor4f = NULL;
10944 rsurface.lightmapcolor4f_bufferobject = 0;
10945 rsurface.lightmapcolor4f_bufferoffset = 0;
10947 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10949 qboolean applycolor = true;
10952 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10954 r_refdef.lightmapintensity = 1;
10955 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10956 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10960 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10962 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10963 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10964 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10967 if(!rsurface.lightmapcolor4f)
10968 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10970 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10971 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10972 if(r_refdef.fogenabled)
10973 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10975 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10976 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10979 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10982 RSurf_SetupDepthAndCulling();
10983 if (r_showsurfaces.integer == 3 && !prepass)
10985 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10988 switch (vid.renderpath)
10990 case RENDERPATH_GL20:
10991 case RENDERPATH_CGGL:
10992 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10994 case RENDERPATH_GL13:
10995 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10997 case RENDERPATH_GL11:
10998 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11004 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11007 RSurf_SetupDepthAndCulling();
11008 if (r_showsurfaces.integer == 3 && !prepass)
11010 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11013 switch (vid.renderpath)
11015 case RENDERPATH_GL20:
11016 case RENDERPATH_CGGL:
11017 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11019 case RENDERPATH_GL13:
11020 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11022 case RENDERPATH_GL11:
11023 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11029 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11032 int texturenumsurfaces, endsurface;
11033 texture_t *texture;
11034 const msurface_t *surface;
11035 const msurface_t *texturesurfacelist[256];
11037 // if the model is static it doesn't matter what value we give for
11038 // wantnormals and wanttangents, so this logic uses only rules applicable
11039 // to a model, knowing that they are meaningless otherwise
11040 if (ent == r_refdef.scene.worldentity)
11041 RSurf_ActiveWorldEntity();
11042 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11043 RSurf_ActiveModelEntity(ent, false, false, false);
11046 switch (vid.renderpath)
11048 case RENDERPATH_GL20:
11049 case RENDERPATH_CGGL:
11050 RSurf_ActiveModelEntity(ent, true, true, false);
11052 case RENDERPATH_GL13:
11053 case RENDERPATH_GL11:
11054 RSurf_ActiveModelEntity(ent, true, false, false);
11059 if (r_transparentdepthmasking.integer)
11061 qboolean setup = false;
11062 for (i = 0;i < numsurfaces;i = j)
11065 surface = rsurface.modelsurfaces + surfacelist[i];
11066 texture = surface->texture;
11067 rsurface.texture = R_GetCurrentTexture(texture);
11068 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11069 // scan ahead until we find a different texture
11070 endsurface = min(i + 1024, numsurfaces);
11071 texturenumsurfaces = 0;
11072 texturesurfacelist[texturenumsurfaces++] = surface;
11073 for (;j < endsurface;j++)
11075 surface = rsurface.modelsurfaces + surfacelist[j];
11076 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11078 texturesurfacelist[texturenumsurfaces++] = surface;
11080 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11082 // render the range of surfaces as depth
11086 GL_ColorMask(0,0,0,0);
11088 GL_DepthTest(true);
11089 GL_BlendFunc(GL_ONE, GL_ZERO);
11090 GL_DepthMask(true);
11091 GL_AlphaTest(false);
11092 R_Mesh_ColorPointer(NULL, 0, 0);
11093 R_Mesh_ResetTextureState();
11094 R_SetupShader_DepthOrShadow();
11096 RSurf_SetupDepthAndCulling();
11097 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11098 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11101 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11104 for (i = 0;i < numsurfaces;i = j)
11107 surface = rsurface.modelsurfaces + surfacelist[i];
11108 texture = surface->texture;
11109 rsurface.texture = R_GetCurrentTexture(texture);
11110 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11111 // scan ahead until we find a different texture
11112 endsurface = min(i + 1024, numsurfaces);
11113 texturenumsurfaces = 0;
11114 texturesurfacelist[texturenumsurfaces++] = surface;
11115 for (;j < endsurface;j++)
11117 surface = rsurface.modelsurfaces + surfacelist[j];
11118 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11120 texturesurfacelist[texturenumsurfaces++] = surface;
11122 // render the range of surfaces
11123 if (ent == r_refdef.scene.worldentity)
11124 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11126 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11128 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11129 GL_AlphaTest(false);
11132 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11134 // transparent surfaces get pushed off into the transparent queue
11135 int surfacelistindex;
11136 const msurface_t *surface;
11137 vec3_t tempcenter, center;
11138 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11140 surface = texturesurfacelist[surfacelistindex];
11141 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11142 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11143 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11144 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11145 if (queueentity->transparent_offset) // transparent offset
11147 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11148 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11149 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11151 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11155 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11157 const entity_render_t *queueentity = r_refdef.scene.worldentity;
11161 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11163 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11165 RSurf_SetupDepthAndCulling();
11166 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11167 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11171 if (!rsurface.texture->currentnumlayers)
11173 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11174 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11176 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11178 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11180 RSurf_SetupDepthAndCulling();
11181 GL_AlphaTest(false);
11182 R_Mesh_ColorPointer(NULL, 0, 0);
11183 R_Mesh_ResetTextureState();
11184 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11185 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11186 GL_DepthMask(true);
11187 GL_BlendFunc(GL_ONE, GL_ZERO);
11188 GL_Color(0, 0, 0, 1);
11189 GL_DepthTest(writedepth);
11190 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11192 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11194 RSurf_SetupDepthAndCulling();
11195 GL_AlphaTest(false);
11196 R_Mesh_ColorPointer(NULL, 0, 0);
11197 R_Mesh_ResetTextureState();
11198 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11199 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11200 GL_DepthMask(true);
11201 GL_BlendFunc(GL_ONE, GL_ZERO);
11202 GL_DepthTest(true);
11203 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11205 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11206 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11207 else if (!rsurface.texture->currentnumlayers)
11209 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11211 // in the deferred case, transparent surfaces were queued during prepass
11212 if (!r_shadow_usingdeferredprepass)
11213 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11217 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11218 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11223 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11226 texture_t *texture;
11227 // break the surface list down into batches by texture and use of lightmapping
11228 for (i = 0;i < numsurfaces;i = j)
11231 // texture is the base texture pointer, rsurface.texture is the
11232 // current frame/skin the texture is directing us to use (for example
11233 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11234 // use skin 1 instead)
11235 texture = surfacelist[i]->texture;
11236 rsurface.texture = R_GetCurrentTexture(texture);
11237 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11238 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11240 // if this texture is not the kind we want, skip ahead to the next one
11241 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11245 // simply scan ahead until we find a different texture or lightmap state
11246 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11248 // render the range of surfaces
11249 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11253 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11258 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11260 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11262 RSurf_SetupDepthAndCulling();
11263 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11264 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11268 if (!rsurface.texture->currentnumlayers)
11270 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11271 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11273 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11275 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11277 RSurf_SetupDepthAndCulling();
11278 GL_AlphaTest(false);
11279 R_Mesh_ColorPointer(NULL, 0, 0);
11280 R_Mesh_ResetTextureState();
11281 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11282 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11283 GL_DepthMask(true);
11284 GL_BlendFunc(GL_ONE, GL_ZERO);
11285 GL_Color(0, 0, 0, 1);
11286 GL_DepthTest(writedepth);
11287 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11289 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11291 RSurf_SetupDepthAndCulling();
11292 GL_AlphaTest(false);
11293 R_Mesh_ColorPointer(NULL, 0, 0);
11294 R_Mesh_ResetTextureState();
11295 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11296 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11297 GL_DepthMask(true);
11298 GL_BlendFunc(GL_ONE, GL_ZERO);
11299 GL_DepthTest(true);
11300 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11302 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11303 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11304 else if (!rsurface.texture->currentnumlayers)
11306 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11308 // in the deferred case, transparent surfaces were queued during prepass
11309 if (!r_shadow_usingdeferredprepass)
11310 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11314 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11315 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11320 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11323 texture_t *texture;
11324 // break the surface list down into batches by texture and use of lightmapping
11325 for (i = 0;i < numsurfaces;i = j)
11328 // texture is the base texture pointer, rsurface.texture is the
11329 // current frame/skin the texture is directing us to use (for example
11330 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11331 // use skin 1 instead)
11332 texture = surfacelist[i]->texture;
11333 rsurface.texture = R_GetCurrentTexture(texture);
11334 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11335 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11337 // if this texture is not the kind we want, skip ahead to the next one
11338 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11342 // simply scan ahead until we find a different texture or lightmap state
11343 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11345 // render the range of surfaces
11346 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11350 float locboxvertex3f[6*4*3] =
11352 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11353 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11354 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11355 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11356 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11357 1,0,0, 0,0,0, 0,1,0, 1,1,0
11360 unsigned short locboxelements[6*2*3] =
11365 12,13,14, 12,14,15,
11366 16,17,18, 16,18,19,
11370 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11373 cl_locnode_t *loc = (cl_locnode_t *)ent;
11375 float vertex3f[6*4*3];
11377 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11378 GL_DepthMask(false);
11379 GL_DepthRange(0, 1);
11380 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11381 GL_DepthTest(true);
11382 GL_CullFace(GL_NONE);
11383 R_EntityMatrix(&identitymatrix);
11385 R_Mesh_VertexPointer(vertex3f, 0, 0);
11386 R_Mesh_ColorPointer(NULL, 0, 0);
11387 R_Mesh_ResetTextureState();
11388 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11390 i = surfacelist[0];
11391 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11392 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11393 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11394 surfacelist[0] < 0 ? 0.5f : 0.125f);
11396 if (VectorCompare(loc->mins, loc->maxs))
11398 VectorSet(size, 2, 2, 2);
11399 VectorMA(loc->mins, -0.5f, size, mins);
11403 VectorCopy(loc->mins, mins);
11404 VectorSubtract(loc->maxs, loc->mins, size);
11407 for (i = 0;i < 6*4*3;)
11408 for (j = 0;j < 3;j++, i++)
11409 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11411 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11414 void R_DrawLocs(void)
11417 cl_locnode_t *loc, *nearestloc;
11419 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11420 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11422 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11423 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11427 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11429 if (decalsystem->decals)
11430 Mem_Free(decalsystem->decals);
11431 memset(decalsystem, 0, sizeof(*decalsystem));
11434 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)
11437 tridecal_t *decals;
11440 // expand or initialize the system
11441 if (decalsystem->maxdecals <= decalsystem->numdecals)
11443 decalsystem_t old = *decalsystem;
11444 qboolean useshortelements;
11445 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11446 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11447 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)));
11448 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11449 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11450 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11451 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11452 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11453 if (decalsystem->numdecals)
11454 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11456 Mem_Free(old.decals);
11457 for (i = 0;i < decalsystem->maxdecals*3;i++)
11458 decalsystem->element3i[i] = i;
11459 if (useshortelements)
11460 for (i = 0;i < decalsystem->maxdecals*3;i++)
11461 decalsystem->element3s[i] = i;
11464 // grab a decal and search for another free slot for the next one
11465 decals = decalsystem->decals;
11466 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11467 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11469 decalsystem->freedecal = i;
11470 if (decalsystem->numdecals <= i)
11471 decalsystem->numdecals = i + 1;
11473 // initialize the decal
11475 decal->triangleindex = triangleindex;
11476 decal->surfaceindex = surfaceindex;
11477 decal->decalsequence = decalsequence;
11478 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11479 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11480 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11481 decal->color4ub[0][3] = 255;
11482 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11483 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11484 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11485 decal->color4ub[1][3] = 255;
11486 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11487 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11488 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11489 decal->color4ub[2][3] = 255;
11490 decal->vertex3f[0][0] = v0[0];
11491 decal->vertex3f[0][1] = v0[1];
11492 decal->vertex3f[0][2] = v0[2];
11493 decal->vertex3f[1][0] = v1[0];
11494 decal->vertex3f[1][1] = v1[1];
11495 decal->vertex3f[1][2] = v1[2];
11496 decal->vertex3f[2][0] = v2[0];
11497 decal->vertex3f[2][1] = v2[1];
11498 decal->vertex3f[2][2] = v2[2];
11499 decal->texcoord2f[0][0] = t0[0];
11500 decal->texcoord2f[0][1] = t0[1];
11501 decal->texcoord2f[1][0] = t1[0];
11502 decal->texcoord2f[1][1] = t1[1];
11503 decal->texcoord2f[2][0] = t2[0];
11504 decal->texcoord2f[2][1] = t2[1];
11507 extern cvar_t cl_decals_bias;
11508 extern cvar_t cl_decals_models;
11509 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11510 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)
11512 matrix4x4_t projection;
11513 decalsystem_t *decalsystem;
11516 const float *vertex3f;
11517 const msurface_t *surface;
11518 const msurface_t *surfaces;
11519 const int *surfacelist;
11520 const texture_t *texture;
11522 int numsurfacelist;
11523 int surfacelistindex;
11530 float localorigin[3];
11531 float localnormal[3];
11532 float localmins[3];
11533 float localmaxs[3];
11539 float planes[6][4];
11541 float points[2][9][3];
11545 decalsystem = &ent->decalsystem;
11546 model = ent->model;
11547 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11549 R_DecalSystem_Reset(&ent->decalsystem);
11553 if (!model->brush.data_nodes && !cl_decals_models.integer)
11555 if (decalsystem->model)
11556 R_DecalSystem_Reset(decalsystem);
11560 if (decalsystem->model != model)
11561 R_DecalSystem_Reset(decalsystem);
11562 decalsystem->model = model;
11564 RSurf_ActiveModelEntity(ent, false, false, false);
11566 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11567 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11568 VectorNormalize(localnormal);
11569 localsize = worldsize*rsurface.inversematrixscale;
11570 localmins[0] = localorigin[0] - localsize;
11571 localmins[1] = localorigin[1] - localsize;
11572 localmins[2] = localorigin[2] - localsize;
11573 localmaxs[0] = localorigin[0] + localsize;
11574 localmaxs[1] = localorigin[1] + localsize;
11575 localmaxs[2] = localorigin[2] + localsize;
11577 //VectorCopy(localnormal, planes[4]);
11578 //VectorVectors(planes[4], planes[2], planes[0]);
11579 AnglesFromVectors(angles, localnormal, NULL, false);
11580 AngleVectors(angles, planes[0], planes[2], planes[4]);
11581 VectorNegate(planes[0], planes[1]);
11582 VectorNegate(planes[2], planes[3]);
11583 VectorNegate(planes[4], planes[5]);
11584 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11585 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11586 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11587 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11588 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11589 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11594 matrix4x4_t forwardprojection;
11595 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11596 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11601 float projectionvector[4][3];
11602 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11603 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11604 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11605 projectionvector[0][0] = planes[0][0] * ilocalsize;
11606 projectionvector[0][1] = planes[1][0] * ilocalsize;
11607 projectionvector[0][2] = planes[2][0] * ilocalsize;
11608 projectionvector[1][0] = planes[0][1] * ilocalsize;
11609 projectionvector[1][1] = planes[1][1] * ilocalsize;
11610 projectionvector[1][2] = planes[2][1] * ilocalsize;
11611 projectionvector[2][0] = planes[0][2] * ilocalsize;
11612 projectionvector[2][1] = planes[1][2] * ilocalsize;
11613 projectionvector[2][2] = planes[2][2] * ilocalsize;
11614 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11615 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11616 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11617 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11621 dynamic = model->surfmesh.isanimated;
11622 vertex3f = rsurface.modelvertex3f;
11623 numsurfacelist = model->nummodelsurfaces;
11624 surfacelist = model->sortedmodelsurfaces;
11625 surfaces = model->data_surfaces;
11626 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11628 surfaceindex = surfacelist[surfacelistindex];
11629 surface = surfaces + surfaceindex;
11630 // check cull box first because it rejects more than any other check
11631 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11633 // skip transparent surfaces
11634 texture = surface->texture;
11635 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11637 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11639 numtriangles = surface->num_triangles;
11640 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11642 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11644 index = 3*e[cornerindex];
11645 VectorCopy(vertex3f + index, v[cornerindex]);
11648 //TriangleNormal(v[0], v[1], v[2], normal);
11649 //if (DotProduct(normal, localnormal) < 0.0f)
11651 // clip by each of the box planes formed from the projection matrix
11652 // if anything survives, we emit the decal
11653 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]);
11656 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]);
11659 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]);
11662 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]);
11665 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]);
11668 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]);
11671 // some part of the triangle survived, so we have to accept it...
11674 // dynamic always uses the original triangle
11676 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11678 index = 3*e[cornerindex];
11679 VectorCopy(vertex3f + index, v[cornerindex]);
11682 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11684 // convert vertex positions to texcoords
11685 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11686 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11687 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11688 // calculate distance fade from the projection origin
11689 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11690 f = bound(0.0f, f, 1.0f);
11691 c[cornerindex][0] = r * f;
11692 c[cornerindex][1] = g * f;
11693 c[cornerindex][2] = b * f;
11694 c[cornerindex][3] = 1.0f;
11695 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11698 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);
11700 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11701 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);
11706 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11707 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)
11709 int renderentityindex;
11710 float worldmins[3];
11711 float worldmaxs[3];
11712 entity_render_t *ent;
11714 if (!cl_decals_newsystem.integer)
11717 worldmins[0] = worldorigin[0] - worldsize;
11718 worldmins[1] = worldorigin[1] - worldsize;
11719 worldmins[2] = worldorigin[2] - worldsize;
11720 worldmaxs[0] = worldorigin[0] + worldsize;
11721 worldmaxs[1] = worldorigin[1] + worldsize;
11722 worldmaxs[2] = worldorigin[2] + worldsize;
11724 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11726 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11728 ent = r_refdef.scene.entities[renderentityindex];
11729 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11732 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11736 typedef struct r_decalsystem_splatqueue_s
11738 vec3_t worldorigin;
11739 vec3_t worldnormal;
11745 r_decalsystem_splatqueue_t;
11747 int r_decalsystem_numqueued = 0;
11748 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11750 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)
11752 r_decalsystem_splatqueue_t *queue;
11754 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11757 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11758 VectorCopy(worldorigin, queue->worldorigin);
11759 VectorCopy(worldnormal, queue->worldnormal);
11760 Vector4Set(queue->color, r, g, b, a);
11761 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11762 queue->worldsize = worldsize;
11763 queue->decalsequence = cl.decalsequence++;
11766 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11769 r_decalsystem_splatqueue_t *queue;
11771 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11772 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);
11773 r_decalsystem_numqueued = 0;
11776 extern cvar_t cl_decals_max;
11777 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11780 decalsystem_t *decalsystem = &ent->decalsystem;
11787 if (!decalsystem->numdecals)
11790 if (r_showsurfaces.integer)
11793 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11795 R_DecalSystem_Reset(decalsystem);
11799 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11800 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11802 if (decalsystem->lastupdatetime)
11803 frametime = (cl.time - decalsystem->lastupdatetime);
11806 decalsystem->lastupdatetime = cl.time;
11807 decal = decalsystem->decals;
11808 numdecals = decalsystem->numdecals;
11810 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11812 if (decal->color4ub[0][3])
11814 decal->lived += frametime;
11815 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11817 memset(decal, 0, sizeof(*decal));
11818 if (decalsystem->freedecal > i)
11819 decalsystem->freedecal = i;
11823 decal = decalsystem->decals;
11824 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11827 // collapse the array by shuffling the tail decals into the gaps
11830 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11831 decalsystem->freedecal++;
11832 if (decalsystem->freedecal == numdecals)
11834 decal[decalsystem->freedecal] = decal[--numdecals];
11837 decalsystem->numdecals = numdecals;
11839 if (numdecals <= 0)
11841 // if there are no decals left, reset decalsystem
11842 R_DecalSystem_Reset(decalsystem);
11846 extern skinframe_t *decalskinframe;
11847 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11850 decalsystem_t *decalsystem = &ent->decalsystem;
11859 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11862 numdecals = decalsystem->numdecals;
11866 if (r_showsurfaces.integer)
11869 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11871 R_DecalSystem_Reset(decalsystem);
11875 // if the model is static it doesn't matter what value we give for
11876 // wantnormals and wanttangents, so this logic uses only rules applicable
11877 // to a model, knowing that they are meaningless otherwise
11878 if (ent == r_refdef.scene.worldentity)
11879 RSurf_ActiveWorldEntity();
11881 RSurf_ActiveModelEntity(ent, false, false, false);
11883 decalsystem->lastupdatetime = cl.time;
11884 decal = decalsystem->decals;
11886 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11888 // update vertex positions for animated models
11889 v3f = decalsystem->vertex3f;
11890 c4f = decalsystem->color4f;
11891 t2f = decalsystem->texcoord2f;
11892 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11894 if (!decal->color4ub[0][3])
11897 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11900 // update color values for fading decals
11901 if (decal->lived >= cl_decals_time.value)
11903 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11904 alpha *= (1.0f/255.0f);
11907 alpha = 1.0f/255.0f;
11909 c4f[ 0] = decal->color4ub[0][0] * alpha;
11910 c4f[ 1] = decal->color4ub[0][1] * alpha;
11911 c4f[ 2] = decal->color4ub[0][2] * alpha;
11913 c4f[ 4] = decal->color4ub[1][0] * alpha;
11914 c4f[ 5] = decal->color4ub[1][1] * alpha;
11915 c4f[ 6] = decal->color4ub[1][2] * alpha;
11917 c4f[ 8] = decal->color4ub[2][0] * alpha;
11918 c4f[ 9] = decal->color4ub[2][1] * alpha;
11919 c4f[10] = decal->color4ub[2][2] * alpha;
11922 t2f[0] = decal->texcoord2f[0][0];
11923 t2f[1] = decal->texcoord2f[0][1];
11924 t2f[2] = decal->texcoord2f[1][0];
11925 t2f[3] = decal->texcoord2f[1][1];
11926 t2f[4] = decal->texcoord2f[2][0];
11927 t2f[5] = decal->texcoord2f[2][1];
11929 // update vertex positions for animated models
11930 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11932 e = rsurface.modelelement3i + 3*decal->triangleindex;
11933 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11934 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11935 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11939 VectorCopy(decal->vertex3f[0], v3f);
11940 VectorCopy(decal->vertex3f[1], v3f + 3);
11941 VectorCopy(decal->vertex3f[2], v3f + 6);
11952 r_refdef.stats.drawndecals += numtris;
11954 if (r_refdef.fogenabled)
11956 switch(vid.renderpath)
11958 case RENDERPATH_GL20:
11959 case RENDERPATH_CGGL:
11960 case RENDERPATH_GL13:
11961 case RENDERPATH_GL11:
11962 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11964 alpha = RSurf_FogVertex(v3f);
11973 // now render the decals all at once
11974 // (this assumes they all use one particle font texture!)
11975 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);
11976 R_Mesh_ResetTextureState();
11977 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11978 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11979 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11980 GL_DepthMask(false);
11981 GL_DepthRange(0, 1);
11982 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11983 GL_DepthTest(true);
11984 GL_CullFace(GL_NONE);
11985 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11986 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11987 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11991 static void R_DrawModelDecals(void)
11995 // fade faster when there are too many decals
11996 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11997 for (i = 0;i < r_refdef.scene.numentities;i++)
11998 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12000 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12001 for (i = 0;i < r_refdef.scene.numentities;i++)
12002 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12003 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12005 R_DecalSystem_ApplySplatEntitiesQueue();
12007 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12008 for (i = 0;i < r_refdef.scene.numentities;i++)
12009 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12011 r_refdef.stats.totaldecals += numdecals;
12013 if (r_showsurfaces.integer)
12016 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12018 for (i = 0;i < r_refdef.scene.numentities;i++)
12020 if (!r_refdef.viewcache.entityvisible[i])
12022 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12023 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12027 void R_DrawDebugModel(void)
12029 entity_render_t *ent = rsurface.entity;
12030 int i, j, k, l, flagsmask;
12032 const msurface_t *surface;
12033 dp_model_t *model = ent->model;
12036 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12038 R_Mesh_ColorPointer(NULL, 0, 0);
12039 R_Mesh_ResetTextureState();
12040 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12041 GL_DepthRange(0, 1);
12042 GL_DepthTest(!r_showdisabledepthtest.integer);
12043 GL_DepthMask(false);
12044 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12046 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
12048 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12049 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
12051 if (brush->colbrushf && brush->colbrushf->numtriangles)
12053 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12054 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);
12055 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12058 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
12060 if (surface->num_collisiontriangles)
12062 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
12063 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);
12064 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
12069 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12071 if (r_showtris.integer || r_shownormals.integer)
12073 if (r_showdisabledepthtest.integer)
12075 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12076 GL_DepthMask(false);
12080 GL_BlendFunc(GL_ONE, GL_ZERO);
12081 GL_DepthMask(true);
12083 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12085 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12087 rsurface.texture = R_GetCurrentTexture(surface->texture);
12088 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12090 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12091 if (r_showtris.value > 0)
12093 if (!rsurface.texture->currentlayers->depthmask)
12094 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12095 else if (ent == r_refdef.scene.worldentity)
12096 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12098 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12099 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12100 R_Mesh_ColorPointer(NULL, 0, 0);
12101 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12102 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12103 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12104 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);
12105 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12108 if (r_shownormals.value < 0)
12110 qglBegin(GL_LINES);
12111 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12113 VectorCopy(rsurface.vertex3f + l * 3, v);
12114 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12115 qglVertex3f(v[0], v[1], v[2]);
12116 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12117 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12118 qglVertex3f(v[0], v[1], v[2]);
12123 if (r_shownormals.value > 0)
12125 qglBegin(GL_LINES);
12126 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12128 VectorCopy(rsurface.vertex3f + l * 3, v);
12129 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12130 qglVertex3f(v[0], v[1], v[2]);
12131 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12132 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12133 qglVertex3f(v[0], v[1], v[2]);
12137 qglBegin(GL_LINES);
12138 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12140 VectorCopy(rsurface.vertex3f + l * 3, v);
12141 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12142 qglVertex3f(v[0], v[1], v[2]);
12143 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12144 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12145 qglVertex3f(v[0], v[1], v[2]);
12149 qglBegin(GL_LINES);
12150 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12152 VectorCopy(rsurface.vertex3f + l * 3, v);
12153 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12154 qglVertex3f(v[0], v[1], v[2]);
12155 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12156 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12157 qglVertex3f(v[0], v[1], v[2]);
12164 rsurface.texture = NULL;
12168 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12169 int r_maxsurfacelist = 0;
12170 const msurface_t **r_surfacelist = NULL;
12171 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12173 int i, j, endj, flagsmask;
12174 dp_model_t *model = r_refdef.scene.worldmodel;
12175 msurface_t *surfaces;
12176 unsigned char *update;
12177 int numsurfacelist = 0;
12181 if (r_maxsurfacelist < model->num_surfaces)
12183 r_maxsurfacelist = model->num_surfaces;
12185 Mem_Free((msurface_t**)r_surfacelist);
12186 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12189 RSurf_ActiveWorldEntity();
12191 surfaces = model->data_surfaces;
12192 update = model->brushq1.lightmapupdateflags;
12194 // update light styles on this submodel
12195 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12197 model_brush_lightstyleinfo_t *style;
12198 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12200 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12202 int *list = style->surfacelist;
12203 style->value = r_refdef.scene.lightstylevalue[style->style];
12204 for (j = 0;j < style->numsurfaces;j++)
12205 update[list[j]] = true;
12210 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12214 R_DrawDebugModel();
12215 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12219 rsurface.uselightmaptexture = false;
12220 rsurface.texture = NULL;
12221 rsurface.rtlight = NULL;
12222 numsurfacelist = 0;
12223 // add visible surfaces to draw list
12224 for (i = 0;i < model->nummodelsurfaces;i++)
12226 j = model->sortedmodelsurfaces[i];
12227 if (r_refdef.viewcache.world_surfacevisible[j])
12228 r_surfacelist[numsurfacelist++] = surfaces + j;
12230 // update lightmaps if needed
12231 if (model->brushq1.firstrender)
12233 model->brushq1.firstrender = false;
12234 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12236 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12240 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12241 if (r_refdef.viewcache.world_surfacevisible[j])
12243 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12245 // don't do anything if there were no surfaces
12246 if (!numsurfacelist)
12248 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12251 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12252 GL_AlphaTest(false);
12254 // add to stats if desired
12255 if (r_speeds.integer && !skysurfaces && !depthonly)
12257 r_refdef.stats.world_surfaces += numsurfacelist;
12258 for (j = 0;j < numsurfacelist;j++)
12259 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12262 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12265 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12267 int i, j, endj, flagsmask;
12268 dp_model_t *model = ent->model;
12269 msurface_t *surfaces;
12270 unsigned char *update;
12271 int numsurfacelist = 0;
12275 if (r_maxsurfacelist < model->num_surfaces)
12277 r_maxsurfacelist = model->num_surfaces;
12279 Mem_Free((msurface_t **)r_surfacelist);
12280 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12283 // if the model is static it doesn't matter what value we give for
12284 // wantnormals and wanttangents, so this logic uses only rules applicable
12285 // to a model, knowing that they are meaningless otherwise
12286 if (ent == r_refdef.scene.worldentity)
12287 RSurf_ActiveWorldEntity();
12288 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12289 RSurf_ActiveModelEntity(ent, false, false, false);
12291 RSurf_ActiveModelEntity(ent, true, true, true);
12292 else if (depthonly)
12293 RSurf_ActiveModelEntity(ent, false, false, false);
12296 switch (vid.renderpath)
12298 case RENDERPATH_GL20:
12299 case RENDERPATH_CGGL:
12300 RSurf_ActiveModelEntity(ent, true, true, false);
12302 case RENDERPATH_GL13:
12303 case RENDERPATH_GL11:
12304 RSurf_ActiveModelEntity(ent, true, false, false);
12309 surfaces = model->data_surfaces;
12310 update = model->brushq1.lightmapupdateflags;
12312 // update light styles
12313 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12315 model_brush_lightstyleinfo_t *style;
12316 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12318 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12320 int *list = style->surfacelist;
12321 style->value = r_refdef.scene.lightstylevalue[style->style];
12322 for (j = 0;j < style->numsurfaces;j++)
12323 update[list[j]] = true;
12328 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12332 R_DrawDebugModel();
12333 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12337 rsurface.uselightmaptexture = false;
12338 rsurface.texture = NULL;
12339 rsurface.rtlight = NULL;
12340 numsurfacelist = 0;
12341 // add visible surfaces to draw list
12342 for (i = 0;i < model->nummodelsurfaces;i++)
12343 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12344 // don't do anything if there were no surfaces
12345 if (!numsurfacelist)
12347 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12350 // update lightmaps if needed
12354 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12359 R_BuildLightMap(ent, surfaces + j);
12364 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12366 R_BuildLightMap(ent, surfaces + j);
12367 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12368 GL_AlphaTest(false);
12370 // add to stats if desired
12371 if (r_speeds.integer && !skysurfaces && !depthonly)
12373 r_refdef.stats.entities_surfaces += numsurfacelist;
12374 for (j = 0;j < numsurfacelist;j++)
12375 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12378 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12381 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12383 static texture_t texture;
12384 static msurface_t surface;
12385 const msurface_t *surfacelist = &surface;
12387 // fake enough texture and surface state to render this geometry
12389 texture.update_lastrenderframe = -1; // regenerate this texture
12390 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12391 texture.currentskinframe = skinframe;
12392 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12393 texture.specularscalemod = 1;
12394 texture.specularpowermod = 1;
12396 surface.texture = &texture;
12397 surface.num_triangles = numtriangles;
12398 surface.num_firsttriangle = firsttriangle;
12399 surface.num_vertices = numvertices;
12400 surface.num_firstvertex = firstvertex;
12403 rsurface.texture = R_GetCurrentTexture(surface.texture);
12404 rsurface.uselightmaptexture = false;
12405 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12408 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)
12410 static msurface_t surface;
12411 const msurface_t *surfacelist = &surface;
12413 // fake enough texture and surface state to render this geometry
12415 surface.texture = texture;
12416 surface.num_triangles = numtriangles;
12417 surface.num_firsttriangle = firsttriangle;
12418 surface.num_vertices = numvertices;
12419 surface.num_firstvertex = firstvertex;
12422 rsurface.texture = R_GetCurrentTexture(surface.texture);
12423 rsurface.uselightmaptexture = false;
12424 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);