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
8202 if (r_timereport_active)
8203 R_TimeReport("sky");
8207 R_AnimCache_CacheVisibleEntities();
8208 if (r_timereport_active)
8209 R_TimeReport("animation");
8211 R_Shadow_PrepareLights();
8212 if (r_timereport_active)
8213 R_TimeReport("preparelights");
8215 if (r_shadow_usingdeferredprepass)
8216 R_Shadow_DrawPrepass();
8218 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8220 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8221 if (r_timereport_active)
8222 R_TimeReport("worlddepth");
8224 if (r_depthfirst.integer >= 2)
8226 R_DrawModelsDepth();
8227 if (r_timereport_active)
8228 R_TimeReport("modeldepth");
8231 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8233 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8234 if (r_timereport_active)
8235 R_TimeReport("world");
8238 // don't let sound skip if going slow
8239 if (r_refdef.scene.extraupdate)
8243 if (r_timereport_active)
8244 R_TimeReport("models");
8246 // don't let sound skip if going slow
8247 if (r_refdef.scene.extraupdate)
8250 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8252 R_DrawModelShadows();
8253 R_ResetViewRendering3D();
8254 // don't let sound skip if going slow
8255 if (r_refdef.scene.extraupdate)
8259 if (!r_shadow_usingdeferredprepass)
8261 R_Shadow_DrawLights();
8262 if (r_timereport_active)
8263 R_TimeReport("rtlights");
8266 // don't let sound skip if going slow
8267 if (r_refdef.scene.extraupdate)
8270 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8272 R_DrawModelShadows();
8273 R_ResetViewRendering3D();
8274 // don't let sound skip if going slow
8275 if (r_refdef.scene.extraupdate)
8279 if (cl.csqc_vidvars.drawworld)
8281 if (cl_decals_newsystem.integer)
8283 R_DrawModelDecals();
8284 if (r_timereport_active)
8285 R_TimeReport("modeldecals");
8290 if (r_timereport_active)
8291 R_TimeReport("decals");
8295 if (r_timereport_active)
8296 R_TimeReport("particles");
8299 if (r_timereport_active)
8300 R_TimeReport("explosions");
8302 R_DrawLightningBeams();
8303 if (r_timereport_active)
8304 R_TimeReport("lightning");
8307 VM_CL_AddPolygonsToMeshQueue();
8309 if (r_refdef.view.showdebug)
8311 if (cl_locs_show.integer)
8314 if (r_timereport_active)
8315 R_TimeReport("showlocs");
8318 if (r_drawportals.integer)
8321 if (r_timereport_active)
8322 R_TimeReport("portals");
8325 if (r_showbboxes.value > 0)
8327 R_DrawEntityBBoxes();
8328 if (r_timereport_active)
8329 R_TimeReport("bboxes");
8333 R_MeshQueue_RenderTransparent();
8334 if (r_timereport_active)
8335 R_TimeReport("drawtrans");
8337 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))
8339 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8340 if (r_timereport_active)
8341 R_TimeReport("worlddebug");
8342 R_DrawModelsDebug();
8343 if (r_timereport_active)
8344 R_TimeReport("modeldebug");
8347 if (cl.csqc_vidvars.drawworld)
8349 R_Shadow_DrawCoronas();
8350 if (r_timereport_active)
8351 R_TimeReport("coronas");
8354 // don't let sound skip if going slow
8355 if (r_refdef.scene.extraupdate)
8358 R_ResetViewRendering2D();
8361 static const unsigned short bboxelements[36] =
8371 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8374 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8376 RSurf_ActiveWorldEntity();
8378 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8379 GL_DepthMask(false);
8380 GL_DepthRange(0, 1);
8381 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8382 R_Mesh_ResetTextureState();
8384 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8385 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8386 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8387 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8388 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8389 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8390 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8391 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8392 R_FillColors(color4f, 8, cr, cg, cb, ca);
8393 if (r_refdef.fogenabled)
8395 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8397 f1 = RSurf_FogVertex(v);
8399 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8400 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8401 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8404 R_Mesh_VertexPointer(vertex3f, 0, 0);
8405 R_Mesh_ColorPointer(color4f, 0, 0);
8406 R_Mesh_ResetTextureState();
8407 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8408 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8411 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8415 prvm_edict_t *edict;
8416 prvm_prog_t *prog_save = prog;
8418 // this function draws bounding boxes of server entities
8422 GL_CullFace(GL_NONE);
8423 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8427 for (i = 0;i < numsurfaces;i++)
8429 edict = PRVM_EDICT_NUM(surfacelist[i]);
8430 switch ((int)edict->fields.server->solid)
8432 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
8433 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
8434 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
8435 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8436 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
8437 default: Vector4Set(color, 0, 0, 0, 0.50);break;
8439 color[3] *= r_showbboxes.value;
8440 color[3] = bound(0, color[3], 1);
8441 GL_DepthTest(!r_showdisabledepthtest.integer);
8442 GL_CullFace(r_refdef.view.cullface_front);
8443 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8449 static void R_DrawEntityBBoxes(void)
8452 prvm_edict_t *edict;
8454 prvm_prog_t *prog_save = prog;
8456 // this function draws bounding boxes of server entities
8462 for (i = 0;i < prog->num_edicts;i++)
8464 edict = PRVM_EDICT_NUM(i);
8465 if (edict->priv.server->free)
8467 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8468 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8470 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8472 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8473 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8479 static const int nomodelelement3i[24] =
8491 static const unsigned short nomodelelement3s[24] =
8503 static const float nomodelvertex3f[6*3] =
8513 static const float nomodelcolor4f[6*4] =
8515 0.0f, 0.0f, 0.5f, 1.0f,
8516 0.0f, 0.0f, 0.5f, 1.0f,
8517 0.0f, 0.5f, 0.0f, 1.0f,
8518 0.0f, 0.5f, 0.0f, 1.0f,
8519 0.5f, 0.0f, 0.0f, 1.0f,
8520 0.5f, 0.0f, 0.0f, 1.0f
8523 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8529 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);
8531 // this is only called once per entity so numsurfaces is always 1, and
8532 // surfacelist is always {0}, so this code does not handle batches
8534 if (rsurface.ent_flags & RENDER_ADDITIVE)
8536 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8537 GL_DepthMask(false);
8539 else if (rsurface.colormod[3] < 1)
8541 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8542 GL_DepthMask(false);
8546 GL_BlendFunc(GL_ONE, GL_ZERO);
8549 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8550 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8551 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8552 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8553 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8554 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8555 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8556 R_Mesh_ColorPointer(color4f, 0, 0);
8557 for (i = 0, c = color4f;i < 6;i++, c += 4)
8559 c[0] *= rsurface.colormod[0];
8560 c[1] *= rsurface.colormod[1];
8561 c[2] *= rsurface.colormod[2];
8562 c[3] *= rsurface.colormod[3];
8564 if (r_refdef.fogenabled)
8566 for (i = 0, c = color4f;i < 6;i++, c += 4)
8568 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8570 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8571 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8572 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8575 R_Mesh_ResetTextureState();
8576 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8579 void R_DrawNoModel(entity_render_t *ent)
8582 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8583 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8584 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8586 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8589 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8591 vec3_t right1, right2, diff, normal;
8593 VectorSubtract (org2, org1, normal);
8595 // calculate 'right' vector for start
8596 VectorSubtract (r_refdef.view.origin, org1, diff);
8597 CrossProduct (normal, diff, right1);
8598 VectorNormalize (right1);
8600 // calculate 'right' vector for end
8601 VectorSubtract (r_refdef.view.origin, org2, diff);
8602 CrossProduct (normal, diff, right2);
8603 VectorNormalize (right2);
8605 vert[ 0] = org1[0] + width * right1[0];
8606 vert[ 1] = org1[1] + width * right1[1];
8607 vert[ 2] = org1[2] + width * right1[2];
8608 vert[ 3] = org1[0] - width * right1[0];
8609 vert[ 4] = org1[1] - width * right1[1];
8610 vert[ 5] = org1[2] - width * right1[2];
8611 vert[ 6] = org2[0] - width * right2[0];
8612 vert[ 7] = org2[1] - width * right2[1];
8613 vert[ 8] = org2[2] - width * right2[2];
8614 vert[ 9] = org2[0] + width * right2[0];
8615 vert[10] = org2[1] + width * right2[1];
8616 vert[11] = org2[2] + width * right2[2];
8619 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)
8621 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8622 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8623 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8624 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8625 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8626 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8627 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8628 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8629 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8630 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8631 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8632 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8635 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8640 VectorSet(v, x, y, z);
8641 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8642 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8644 if (i == mesh->numvertices)
8646 if (mesh->numvertices < mesh->maxvertices)
8648 VectorCopy(v, vertex3f);
8649 mesh->numvertices++;
8651 return mesh->numvertices;
8657 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8661 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8662 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8663 e = mesh->element3i + mesh->numtriangles * 3;
8664 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8666 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8667 if (mesh->numtriangles < mesh->maxtriangles)
8672 mesh->numtriangles++;
8674 element[1] = element[2];
8678 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8682 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8683 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8684 e = mesh->element3i + mesh->numtriangles * 3;
8685 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8687 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8688 if (mesh->numtriangles < mesh->maxtriangles)
8693 mesh->numtriangles++;
8695 element[1] = element[2];
8699 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8700 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8702 int planenum, planenum2;
8705 mplane_t *plane, *plane2;
8707 double temppoints[2][256*3];
8708 // figure out how large a bounding box we need to properly compute this brush
8710 for (w = 0;w < numplanes;w++)
8711 maxdist = max(maxdist, fabs(planes[w].dist));
8712 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8713 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8714 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8718 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8719 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8721 if (planenum2 == planenum)
8723 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);
8726 if (tempnumpoints < 3)
8728 // generate elements forming a triangle fan for this polygon
8729 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8733 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)
8735 texturelayer_t *layer;
8736 layer = t->currentlayers + t->currentnumlayers++;
8738 layer->depthmask = depthmask;
8739 layer->blendfunc1 = blendfunc1;
8740 layer->blendfunc2 = blendfunc2;
8741 layer->texture = texture;
8742 layer->texmatrix = *matrix;
8743 layer->color[0] = r;
8744 layer->color[1] = g;
8745 layer->color[2] = b;
8746 layer->color[3] = a;
8749 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8752 index = parms[2] + r_refdef.scene.time * parms[3];
8753 index -= floor(index);
8757 case Q3WAVEFUNC_NONE:
8758 case Q3WAVEFUNC_NOISE:
8759 case Q3WAVEFUNC_COUNT:
8762 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8763 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8764 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8765 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8766 case Q3WAVEFUNC_TRIANGLE:
8768 f = index - floor(index);
8779 return (float)(parms[0] + parms[1] * f);
8782 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8787 matrix4x4_t matrix, temp;
8788 switch(tcmod->tcmod)
8792 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8793 matrix = r_waterscrollmatrix;
8795 matrix = identitymatrix;
8797 case Q3TCMOD_ENTITYTRANSLATE:
8798 // this is used in Q3 to allow the gamecode to control texcoord
8799 // scrolling on the entity, which is not supported in darkplaces yet.
8800 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8802 case Q3TCMOD_ROTATE:
8803 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8804 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8805 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8808 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8810 case Q3TCMOD_SCROLL:
8811 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8813 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8814 w = (int) tcmod->parms[0];
8815 h = (int) tcmod->parms[1];
8816 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8818 idx = (int) floor(f * w * h);
8819 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8821 case Q3TCMOD_STRETCH:
8822 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8823 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8825 case Q3TCMOD_TRANSFORM:
8826 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8827 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8828 VectorSet(tcmat + 6, 0 , 0 , 1);
8829 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8830 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8832 case Q3TCMOD_TURBULENT:
8833 // this is handled in the RSurf_PrepareVertices function
8834 matrix = identitymatrix;
8838 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8841 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8843 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8844 char name[MAX_QPATH];
8845 skinframe_t *skinframe;
8846 unsigned char pixels[296*194];
8847 strlcpy(cache->name, skinname, sizeof(cache->name));
8848 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8849 if (developer_loading.integer)
8850 Con_Printf("loading %s\n", name);
8851 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8852 if (!skinframe || !skinframe->base)
8855 fs_offset_t filesize;
8857 f = FS_LoadFile(name, tempmempool, true, &filesize);
8860 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8861 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8865 cache->skinframe = skinframe;
8868 texture_t *R_GetCurrentTexture(texture_t *t)
8871 const entity_render_t *ent = rsurface.entity;
8872 dp_model_t *model = ent->model;
8873 q3shaderinfo_layer_tcmod_t *tcmod;
8875 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8876 return t->currentframe;
8877 t->update_lastrenderframe = r_textureframe;
8878 t->update_lastrenderentity = (void *)ent;
8880 // switch to an alternate material if this is a q1bsp animated material
8882 texture_t *texture = t;
8883 int s = rsurface.ent_skinnum;
8884 if ((unsigned int)s >= (unsigned int)model->numskins)
8886 if (model->skinscenes)
8888 if (model->skinscenes[s].framecount > 1)
8889 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8891 s = model->skinscenes[s].firstframe;
8894 t = t + s * model->num_surfaces;
8897 // use an alternate animation if the entity's frame is not 0,
8898 // and only if the texture has an alternate animation
8899 if (rsurface.ent_alttextures && t->anim_total[1])
8900 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8902 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8904 texture->currentframe = t;
8907 // update currentskinframe to be a qw skin or animation frame
8908 if (rsurface.ent_qwskin >= 0)
8910 i = rsurface.ent_qwskin;
8911 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8913 r_qwskincache_size = cl.maxclients;
8915 Mem_Free(r_qwskincache);
8916 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8918 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8919 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8920 t->currentskinframe = r_qwskincache[i].skinframe;
8921 if (t->currentskinframe == NULL)
8922 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8924 else if (t->numskinframes >= 2)
8925 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8926 if (t->backgroundnumskinframes >= 2)
8927 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8929 t->currentmaterialflags = t->basematerialflags;
8930 t->currentalpha = rsurface.colormod[3];
8931 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8932 t->currentalpha *= r_wateralpha.value;
8933 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8934 t->currentalpha *= t->r_water_wateralpha;
8935 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8936 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8937 if (!(rsurface.ent_flags & RENDER_LIGHT))
8938 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8939 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8941 // pick a model lighting mode
8942 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8943 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8945 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8947 if (rsurface.ent_flags & RENDER_ADDITIVE)
8948 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8949 else if (t->currentalpha < 1)
8950 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8951 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8952 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8953 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8954 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8955 if (t->backgroundnumskinframes)
8956 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8957 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8959 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8960 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8963 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8964 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8965 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8967 // there is no tcmod
8968 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8970 t->currenttexmatrix = r_waterscrollmatrix;
8971 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8973 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8975 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8976 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8979 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8980 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8981 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8982 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8984 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8985 if (t->currentskinframe->qpixels)
8986 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8987 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8988 if (!t->basetexture)
8989 t->basetexture = r_texture_notexture;
8990 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8991 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8992 t->nmaptexture = t->currentskinframe->nmap;
8993 if (!t->nmaptexture)
8994 t->nmaptexture = r_texture_blanknormalmap;
8995 t->glosstexture = r_texture_black;
8996 t->glowtexture = t->currentskinframe->glow;
8997 t->fogtexture = t->currentskinframe->fog;
8998 t->reflectmasktexture = t->currentskinframe->reflect;
8999 if (t->backgroundnumskinframes)
9001 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9002 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9003 t->backgroundglosstexture = r_texture_black;
9004 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9005 if (!t->backgroundnmaptexture)
9006 t->backgroundnmaptexture = r_texture_blanknormalmap;
9010 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9011 t->backgroundnmaptexture = r_texture_blanknormalmap;
9012 t->backgroundglosstexture = r_texture_black;
9013 t->backgroundglowtexture = NULL;
9015 t->specularpower = r_shadow_glossexponent.value;
9016 // TODO: store reference values for these in the texture?
9017 t->specularscale = 0;
9018 if (r_shadow_gloss.integer > 0)
9020 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9022 if (r_shadow_glossintensity.value > 0)
9024 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9025 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9026 t->specularscale = r_shadow_glossintensity.value;
9029 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9031 t->glosstexture = r_texture_white;
9032 t->backgroundglosstexture = r_texture_white;
9033 t->specularscale = r_shadow_gloss2intensity.value;
9034 t->specularpower = r_shadow_gloss2exponent.value;
9037 t->specularscale *= t->specularscalemod;
9038 t->specularpower *= t->specularpowermod;
9040 // lightmaps mode looks bad with dlights using actual texturing, so turn
9041 // off the colormap and glossmap, but leave the normalmap on as it still
9042 // accurately represents the shading involved
9043 if (gl_lightmaps.integer)
9045 t->basetexture = r_texture_grey128;
9046 t->pantstexture = r_texture_black;
9047 t->shirttexture = r_texture_black;
9048 t->nmaptexture = r_texture_blanknormalmap;
9049 t->glosstexture = r_texture_black;
9050 t->glowtexture = NULL;
9051 t->fogtexture = NULL;
9052 t->reflectmasktexture = NULL;
9053 t->backgroundbasetexture = NULL;
9054 t->backgroundnmaptexture = r_texture_blanknormalmap;
9055 t->backgroundglosstexture = r_texture_black;
9056 t->backgroundglowtexture = NULL;
9057 t->specularscale = 0;
9058 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9061 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9062 VectorClear(t->dlightcolor);
9063 t->currentnumlayers = 0;
9064 if (t->currentmaterialflags & MATERIALFLAG_WALL)
9066 int blendfunc1, blendfunc2;
9068 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9070 blendfunc1 = GL_SRC_ALPHA;
9071 blendfunc2 = GL_ONE;
9073 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9075 blendfunc1 = GL_SRC_ALPHA;
9076 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9078 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9080 blendfunc1 = t->customblendfunc[0];
9081 blendfunc2 = t->customblendfunc[1];
9085 blendfunc1 = GL_ONE;
9086 blendfunc2 = GL_ZERO;
9088 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9089 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9091 // fullbright is not affected by r_refdef.lightmapintensity
9092 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]);
9093 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9094 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]);
9095 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9096 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]);
9100 vec3_t ambientcolor;
9102 // set the color tint used for lights affecting this surface
9103 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9105 // q3bsp has no lightmap updates, so the lightstylevalue that
9106 // would normally be baked into the lightmap must be
9107 // applied to the color
9108 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9109 if (model->type == mod_brushq3)
9110 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9111 colorscale *= r_refdef.lightmapintensity;
9112 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9113 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9114 // basic lit geometry
9115 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]);
9116 // add pants/shirt if needed
9117 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9118 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]);
9119 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9120 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]);
9121 // now add ambient passes if needed
9122 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9124 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]);
9125 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9126 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]);
9127 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9128 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]);
9131 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9132 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]);
9133 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9135 // if this is opaque use alpha blend which will darken the earlier
9138 // if this is an alpha blended material, all the earlier passes
9139 // were darkened by fog already, so we only need to add the fog
9140 // color ontop through the fog mask texture
9142 // if this is an additive blended material, all the earlier passes
9143 // were darkened by fog already, and we should not add fog color
9144 // (because the background was not darkened, there is no fog color
9145 // that was lost behind it).
9146 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]);
9150 return t->currentframe;
9153 rsurfacestate_t rsurface;
9155 void R_Mesh_ResizeArrays(int newvertices)
9158 if (rsurface.array_size >= newvertices)
9160 if (rsurface.array_modelvertex3f)
9161 Mem_Free(rsurface.array_modelvertex3f);
9162 rsurface.array_size = (newvertices + 1023) & ~1023;
9163 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9164 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
9165 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
9166 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
9167 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
9168 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
9169 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9170 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9171 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
9172 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
9173 rsurface.array_color4f = base + rsurface.array_size * 27;
9174 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9177 void RSurf_ActiveWorldEntity(void)
9179 dp_model_t *model = r_refdef.scene.worldmodel;
9180 //if (rsurface.entity == r_refdef.scene.worldentity)
9182 rsurface.entity = r_refdef.scene.worldentity;
9183 rsurface.skeleton = NULL;
9184 rsurface.ent_skinnum = 0;
9185 rsurface.ent_qwskin = -1;
9186 rsurface.ent_shadertime = 0;
9187 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9188 if (rsurface.array_size < model->surfmesh.num_vertices)
9189 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9190 rsurface.matrix = identitymatrix;
9191 rsurface.inversematrix = identitymatrix;
9192 rsurface.matrixscale = 1;
9193 rsurface.inversematrixscale = 1;
9194 R_EntityMatrix(&identitymatrix);
9195 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9196 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9197 rsurface.fograngerecip = r_refdef.fograngerecip;
9198 rsurface.fogheightfade = r_refdef.fogheightfade;
9199 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9200 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9201 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9202 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9203 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9204 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9205 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9206 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9207 rsurface.colormod[3] = 1;
9208 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);
9209 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9210 rsurface.frameblend[0].lerp = 1;
9211 rsurface.ent_alttextures = false;
9212 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9213 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9214 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9215 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9216 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9217 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9218 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9219 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9220 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9221 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9222 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9223 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9224 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9225 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9226 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9227 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9228 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9229 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9230 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9231 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9232 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9233 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9234 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9235 rsurface.modelelement3i = model->surfmesh.data_element3i;
9236 rsurface.modelelement3s = model->surfmesh.data_element3s;
9237 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9238 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9239 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9240 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9241 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9242 rsurface.modelsurfaces = model->data_surfaces;
9243 rsurface.generatedvertex = false;
9244 rsurface.vertex3f = rsurface.modelvertex3f;
9245 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9246 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9247 rsurface.svector3f = rsurface.modelsvector3f;
9248 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9249 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9250 rsurface.tvector3f = rsurface.modeltvector3f;
9251 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9252 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9253 rsurface.normal3f = rsurface.modelnormal3f;
9254 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9255 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9256 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9259 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9261 dp_model_t *model = ent->model;
9262 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9264 rsurface.entity = (entity_render_t *)ent;
9265 rsurface.skeleton = ent->skeleton;
9266 rsurface.ent_skinnum = ent->skinnum;
9267 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;
9268 rsurface.ent_shadertime = ent->shadertime;
9269 rsurface.ent_flags = ent->flags;
9270 if (rsurface.array_size < model->surfmesh.num_vertices)
9271 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9272 rsurface.matrix = ent->matrix;
9273 rsurface.inversematrix = ent->inversematrix;
9274 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9275 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9276 R_EntityMatrix(&rsurface.matrix);
9277 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9278 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9279 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9280 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9281 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9282 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9283 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9284 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9285 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9286 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9287 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9288 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9289 rsurface.colormod[3] = ent->alpha;
9290 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9291 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9292 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9293 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9294 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9295 if (ent->model->brush.submodel && !prepass)
9297 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9298 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9300 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9302 if (ent->animcache_vertex3f && !r_framedata_failed)
9304 rsurface.modelvertex3f = ent->animcache_vertex3f;
9305 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9306 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9307 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9309 else if (wanttangents)
9311 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9312 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9313 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9314 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9315 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9317 else if (wantnormals)
9319 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9320 rsurface.modelsvector3f = NULL;
9321 rsurface.modeltvector3f = NULL;
9322 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9323 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9327 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9328 rsurface.modelsvector3f = NULL;
9329 rsurface.modeltvector3f = NULL;
9330 rsurface.modelnormal3f = NULL;
9331 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9333 rsurface.modelvertex3f_bufferobject = 0;
9334 rsurface.modelvertex3f_bufferoffset = 0;
9335 rsurface.modelsvector3f_bufferobject = 0;
9336 rsurface.modelsvector3f_bufferoffset = 0;
9337 rsurface.modeltvector3f_bufferobject = 0;
9338 rsurface.modeltvector3f_bufferoffset = 0;
9339 rsurface.modelnormal3f_bufferobject = 0;
9340 rsurface.modelnormal3f_bufferoffset = 0;
9341 rsurface.generatedvertex = true;
9345 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9346 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9347 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9348 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9349 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9350 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9351 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9352 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9353 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9354 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9355 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9356 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9357 rsurface.generatedvertex = false;
9359 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9360 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9361 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9362 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9363 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9364 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9365 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9366 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9367 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9368 rsurface.modelelement3i = model->surfmesh.data_element3i;
9369 rsurface.modelelement3s = model->surfmesh.data_element3s;
9370 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9371 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9372 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9373 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9374 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9375 rsurface.modelsurfaces = model->data_surfaces;
9376 rsurface.vertex3f = rsurface.modelvertex3f;
9377 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9378 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9379 rsurface.svector3f = rsurface.modelsvector3f;
9380 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9381 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9382 rsurface.tvector3f = rsurface.modeltvector3f;
9383 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9384 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9385 rsurface.normal3f = rsurface.modelnormal3f;
9386 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9387 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9388 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9391 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)
9393 rsurface.entity = r_refdef.scene.worldentity;
9394 rsurface.skeleton = NULL;
9395 rsurface.ent_skinnum = 0;
9396 rsurface.ent_qwskin = -1;
9397 rsurface.ent_shadertime = shadertime;
9398 rsurface.ent_flags = entflags;
9399 rsurface.modelnum_vertices = numvertices;
9400 rsurface.modelnum_triangles = numtriangles;
9401 if (rsurface.array_size < rsurface.modelnum_vertices)
9402 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9403 rsurface.matrix = *matrix;
9404 rsurface.inversematrix = *inversematrix;
9405 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9406 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9407 R_EntityMatrix(&rsurface.matrix);
9408 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9409 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9410 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9411 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9412 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9413 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9414 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9415 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9416 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9417 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9418 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9419 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9420 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);
9421 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9422 rsurface.frameblend[0].lerp = 1;
9423 rsurface.ent_alttextures = false;
9424 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9425 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9428 rsurface.modelvertex3f = vertex3f;
9429 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9430 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9431 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9433 else if (wantnormals)
9435 rsurface.modelvertex3f = vertex3f;
9436 rsurface.modelsvector3f = NULL;
9437 rsurface.modeltvector3f = NULL;
9438 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9442 rsurface.modelvertex3f = vertex3f;
9443 rsurface.modelsvector3f = NULL;
9444 rsurface.modeltvector3f = NULL;
9445 rsurface.modelnormal3f = NULL;
9447 rsurface.modelvertex3f_bufferobject = 0;
9448 rsurface.modelvertex3f_bufferoffset = 0;
9449 rsurface.modelsvector3f_bufferobject = 0;
9450 rsurface.modelsvector3f_bufferoffset = 0;
9451 rsurface.modeltvector3f_bufferobject = 0;
9452 rsurface.modeltvector3f_bufferoffset = 0;
9453 rsurface.modelnormal3f_bufferobject = 0;
9454 rsurface.modelnormal3f_bufferoffset = 0;
9455 rsurface.generatedvertex = true;
9456 rsurface.modellightmapcolor4f = color4f;
9457 rsurface.modellightmapcolor4f_bufferobject = 0;
9458 rsurface.modellightmapcolor4f_bufferoffset = 0;
9459 rsurface.modeltexcoordtexture2f = texcoord2f;
9460 rsurface.modeltexcoordtexture2f_bufferobject = 0;
9461 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9462 rsurface.modeltexcoordlightmap2f = NULL;
9463 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9464 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9465 rsurface.modelelement3i = element3i;
9466 rsurface.modelelement3s = element3s;
9467 rsurface.modelelement3i_bufferobject = 0;
9468 rsurface.modelelement3s_bufferobject = 0;
9469 rsurface.modellightmapoffsets = NULL;
9470 rsurface.modelsurfaces = NULL;
9471 rsurface.vertex3f = rsurface.modelvertex3f;
9472 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9473 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9474 rsurface.svector3f = rsurface.modelsvector3f;
9475 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9476 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9477 rsurface.tvector3f = rsurface.modeltvector3f;
9478 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9479 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9480 rsurface.normal3f = rsurface.modelnormal3f;
9481 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9482 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9483 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9485 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9487 if ((wantnormals || wanttangents) && !normal3f)
9488 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9489 if (wanttangents && !svector3f)
9490 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);
9494 float RSurf_FogPoint(const float *v)
9496 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9497 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9498 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9499 float FogHeightFade = r_refdef.fogheightfade;
9501 unsigned int fogmasktableindex;
9502 if (r_refdef.fogplaneviewabove)
9503 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9505 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9506 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9507 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9510 float RSurf_FogVertex(const float *v)
9512 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9513 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9514 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9515 float FogHeightFade = rsurface.fogheightfade;
9517 unsigned int fogmasktableindex;
9518 if (r_refdef.fogplaneviewabove)
9519 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9521 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9522 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9523 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9526 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9527 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9530 int texturesurfaceindex;
9535 const float *v1, *in_tc;
9537 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9539 q3shaderinfo_deform_t *deform;
9540 // 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
9541 if (rsurface.generatedvertex)
9543 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9544 generatenormals = true;
9545 for (i = 0;i < Q3MAXDEFORMS;i++)
9547 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9549 generatetangents = true;
9550 generatenormals = true;
9552 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9553 generatenormals = true;
9555 if (generatenormals && !rsurface.modelnormal3f)
9557 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9558 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9559 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9560 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9562 if (generatetangents && !rsurface.modelsvector3f)
9564 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9565 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9566 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9567 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9568 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9569 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9570 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);
9573 rsurface.vertex3f = rsurface.modelvertex3f;
9574 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9575 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9576 rsurface.svector3f = rsurface.modelsvector3f;
9577 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9578 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9579 rsurface.tvector3f = rsurface.modeltvector3f;
9580 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9581 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9582 rsurface.normal3f = rsurface.modelnormal3f;
9583 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9584 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9585 // if vertices are deformed (sprite flares and things in maps, possibly
9586 // water waves, bulges and other deformations), generate them into
9587 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9588 // (may be static model data or generated data for an animated model, or
9589 // the previous deform pass)
9590 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9592 switch (deform->deform)
9595 case Q3DEFORM_PROJECTIONSHADOW:
9596 case Q3DEFORM_TEXT0:
9597 case Q3DEFORM_TEXT1:
9598 case Q3DEFORM_TEXT2:
9599 case Q3DEFORM_TEXT3:
9600 case Q3DEFORM_TEXT4:
9601 case Q3DEFORM_TEXT5:
9602 case Q3DEFORM_TEXT6:
9603 case Q3DEFORM_TEXT7:
9606 case Q3DEFORM_AUTOSPRITE:
9607 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9608 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9609 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9610 VectorNormalize(newforward);
9611 VectorNormalize(newright);
9612 VectorNormalize(newup);
9613 // make deformed versions of only the model vertices used by the specified surfaces
9614 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9616 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9617 // a single autosprite surface can contain multiple sprites...
9618 for (j = 0;j < surface->num_vertices - 3;j += 4)
9620 VectorClear(center);
9621 for (i = 0;i < 4;i++)
9622 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9623 VectorScale(center, 0.25f, center);
9624 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9625 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9626 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9627 for (i = 0;i < 4;i++)
9629 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9630 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9633 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);
9634 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);
9636 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9637 rsurface.vertex3f_bufferobject = 0;
9638 rsurface.vertex3f_bufferoffset = 0;
9639 rsurface.svector3f = rsurface.array_deformedsvector3f;
9640 rsurface.svector3f_bufferobject = 0;
9641 rsurface.svector3f_bufferoffset = 0;
9642 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9643 rsurface.tvector3f_bufferobject = 0;
9644 rsurface.tvector3f_bufferoffset = 0;
9645 rsurface.normal3f = rsurface.array_deformednormal3f;
9646 rsurface.normal3f_bufferobject = 0;
9647 rsurface.normal3f_bufferoffset = 0;
9649 case Q3DEFORM_AUTOSPRITE2:
9650 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9651 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9652 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9653 VectorNormalize(newforward);
9654 VectorNormalize(newright);
9655 VectorNormalize(newup);
9656 // make deformed versions of only the model vertices used by the specified surfaces
9657 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9659 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9660 const float *v1, *v2;
9670 memset(shortest, 0, sizeof(shortest));
9671 // a single autosprite surface can contain multiple sprites...
9672 for (j = 0;j < surface->num_vertices - 3;j += 4)
9674 VectorClear(center);
9675 for (i = 0;i < 4;i++)
9676 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9677 VectorScale(center, 0.25f, center);
9678 // find the two shortest edges, then use them to define the
9679 // axis vectors for rotating around the central axis
9680 for (i = 0;i < 6;i++)
9682 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9683 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9685 Debug_PolygonBegin(NULL, 0);
9686 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9687 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);
9688 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9691 l = VectorDistance2(v1, v2);
9692 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9694 l += (1.0f / 1024.0f);
9695 if (shortest[0].length2 > l || i == 0)
9697 shortest[1] = shortest[0];
9698 shortest[0].length2 = l;
9699 shortest[0].v1 = v1;
9700 shortest[0].v2 = v2;
9702 else if (shortest[1].length2 > l || i == 1)
9704 shortest[1].length2 = l;
9705 shortest[1].v1 = v1;
9706 shortest[1].v2 = v2;
9709 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9710 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9712 Debug_PolygonBegin(NULL, 0);
9713 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9714 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);
9715 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9718 // this calculates the right vector from the shortest edge
9719 // and the up vector from the edge midpoints
9720 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9721 VectorNormalize(right);
9722 VectorSubtract(end, start, up);
9723 VectorNormalize(up);
9724 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9725 VectorSubtract(rsurface.localvieworigin, center, forward);
9726 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9727 VectorNegate(forward, forward);
9728 VectorReflect(forward, 0, up, forward);
9729 VectorNormalize(forward);
9730 CrossProduct(up, forward, newright);
9731 VectorNormalize(newright);
9733 Debug_PolygonBegin(NULL, 0);
9734 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);
9735 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9736 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9740 Debug_PolygonBegin(NULL, 0);
9741 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9742 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9743 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9746 // rotate the quad around the up axis vector, this is made
9747 // especially easy by the fact we know the quad is flat,
9748 // so we only have to subtract the center position and
9749 // measure distance along the right vector, and then
9750 // multiply that by the newright vector and add back the
9752 // we also need to subtract the old position to undo the
9753 // displacement from the center, which we do with a
9754 // DotProduct, the subtraction/addition of center is also
9755 // optimized into DotProducts here
9756 l = DotProduct(right, center);
9757 for (i = 0;i < 4;i++)
9759 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9760 f = DotProduct(right, v1) - l;
9761 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9764 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);
9765 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);
9767 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9768 rsurface.vertex3f_bufferobject = 0;
9769 rsurface.vertex3f_bufferoffset = 0;
9770 rsurface.svector3f = rsurface.array_deformedsvector3f;
9771 rsurface.svector3f_bufferobject = 0;
9772 rsurface.svector3f_bufferoffset = 0;
9773 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9774 rsurface.tvector3f_bufferobject = 0;
9775 rsurface.tvector3f_bufferoffset = 0;
9776 rsurface.normal3f = rsurface.array_deformednormal3f;
9777 rsurface.normal3f_bufferobject = 0;
9778 rsurface.normal3f_bufferoffset = 0;
9780 case Q3DEFORM_NORMAL:
9781 // deform the normals to make reflections wavey
9782 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9784 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9785 for (j = 0;j < surface->num_vertices;j++)
9788 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9789 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9790 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9791 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9792 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9793 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9794 VectorNormalize(normal);
9796 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);
9798 rsurface.svector3f = rsurface.array_deformedsvector3f;
9799 rsurface.svector3f_bufferobject = 0;
9800 rsurface.svector3f_bufferoffset = 0;
9801 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9802 rsurface.tvector3f_bufferobject = 0;
9803 rsurface.tvector3f_bufferoffset = 0;
9804 rsurface.normal3f = rsurface.array_deformednormal3f;
9805 rsurface.normal3f_bufferobject = 0;
9806 rsurface.normal3f_bufferoffset = 0;
9809 // deform vertex array to make wavey water and flags and such
9810 waveparms[0] = deform->waveparms[0];
9811 waveparms[1] = deform->waveparms[1];
9812 waveparms[2] = deform->waveparms[2];
9813 waveparms[3] = deform->waveparms[3];
9814 // this is how a divisor of vertex influence on deformation
9815 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9816 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9817 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9819 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9820 for (j = 0;j < surface->num_vertices;j++)
9822 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9823 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9824 // if the wavefunc depends on time, evaluate it per-vertex
9827 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9828 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9830 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9833 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9834 rsurface.vertex3f_bufferobject = 0;
9835 rsurface.vertex3f_bufferoffset = 0;
9837 case Q3DEFORM_BULGE:
9838 // deform vertex array to make the surface have moving bulges
9839 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9841 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9842 for (j = 0;j < surface->num_vertices;j++)
9844 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9845 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9848 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9849 rsurface.vertex3f_bufferobject = 0;
9850 rsurface.vertex3f_bufferoffset = 0;
9853 // deform vertex array
9854 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9855 VectorScale(deform->parms, scale, waveparms);
9856 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9858 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9859 for (j = 0;j < surface->num_vertices;j++)
9860 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9862 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9863 rsurface.vertex3f_bufferobject = 0;
9864 rsurface.vertex3f_bufferoffset = 0;
9868 // generate texcoords based on the chosen texcoord source
9869 switch(rsurface.texture->tcgen.tcgen)
9872 case Q3TCGEN_TEXTURE:
9873 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9874 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
9875 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9877 case Q3TCGEN_LIGHTMAP:
9878 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
9879 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9880 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9882 case Q3TCGEN_VECTOR:
9883 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9885 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9886 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)
9888 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9889 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9892 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9893 rsurface.texcoordtexture2f_bufferobject = 0;
9894 rsurface.texcoordtexture2f_bufferoffset = 0;
9896 case Q3TCGEN_ENVIRONMENT:
9897 // make environment reflections using a spheremap
9898 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9900 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9901 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9902 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9903 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9904 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9906 // identical to Q3A's method, but executed in worldspace so
9907 // carried models can be shiny too
9909 float viewer[3], d, reflected[3], worldreflected[3];
9911 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9912 // VectorNormalize(viewer);
9914 d = DotProduct(normal, viewer);
9916 reflected[0] = normal[0]*2*d - viewer[0];
9917 reflected[1] = normal[1]*2*d - viewer[1];
9918 reflected[2] = normal[2]*2*d - viewer[2];
9919 // note: this is proportinal to viewer, so we can normalize later
9921 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9922 VectorNormalize(worldreflected);
9924 // note: this sphere map only uses world x and z!
9925 // so positive and negative y will LOOK THE SAME.
9926 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9927 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9930 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9931 rsurface.texcoordtexture2f_bufferobject = 0;
9932 rsurface.texcoordtexture2f_bufferoffset = 0;
9935 // the only tcmod that needs software vertex processing is turbulent, so
9936 // check for it here and apply the changes if needed
9937 // and we only support that as the first one
9938 // (handling a mixture of turbulent and other tcmods would be problematic
9939 // without punting it entirely to a software path)
9940 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9942 amplitude = rsurface.texture->tcmods[0].parms[1];
9943 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9944 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9946 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9947 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)
9949 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9950 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9953 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9954 rsurface.texcoordtexture2f_bufferobject = 0;
9955 rsurface.texcoordtexture2f_bufferoffset = 0;
9957 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9958 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9959 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9960 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9963 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9966 const msurface_t *surface = texturesurfacelist[0];
9967 const msurface_t *surface2;
9972 // TODO: lock all array ranges before render, rather than on each surface
9973 if (texturenumsurfaces == 1)
9974 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);
9975 else if (r_batchmode.integer == 2)
9977 #define MAXBATCHTRIANGLES 4096
9978 int batchtriangles = 0;
9979 static int batchelements[MAXBATCHTRIANGLES*3];
9980 for (i = 0;i < texturenumsurfaces;i = j)
9982 surface = texturesurfacelist[i];
9984 if (surface->num_triangles > MAXBATCHTRIANGLES)
9986 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);
9989 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9990 batchtriangles = surface->num_triangles;
9991 firstvertex = surface->num_firstvertex;
9992 endvertex = surface->num_firstvertex + surface->num_vertices;
9993 for (;j < texturenumsurfaces;j++)
9995 surface2 = texturesurfacelist[j];
9996 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9998 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9999 batchtriangles += surface2->num_triangles;
10000 firstvertex = min(firstvertex, surface2->num_firstvertex);
10001 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10003 surface2 = texturesurfacelist[j-1];
10004 numvertices = endvertex - firstvertex;
10005 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10008 else if (r_batchmode.integer == 1)
10010 for (i = 0;i < texturenumsurfaces;i = j)
10012 surface = texturesurfacelist[i];
10013 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10014 if (texturesurfacelist[j] != surface2)
10016 surface2 = texturesurfacelist[j-1];
10017 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10018 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10019 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10024 for (i = 0;i < texturenumsurfaces;i++)
10026 surface = texturesurfacelist[i];
10027 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);
10032 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10034 switch(vid.renderpath)
10036 case RENDERPATH_CGGL:
10038 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10039 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10042 case RENDERPATH_GL20:
10043 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10044 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10046 case RENDERPATH_GL13:
10047 case RENDERPATH_GL11:
10048 R_Mesh_TexBind(0, surface->lightmaptexture);
10053 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10055 // pick the closest matching water plane and bind textures
10056 int planeindex, vertexindex;
10060 r_waterstate_waterplane_t *p, *bestp;
10063 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10066 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10068 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10069 d += fabs(PlaneDiff(vert, &p->plane));
10071 if (bestd > d || !bestp)
10077 switch(vid.renderpath)
10079 case RENDERPATH_CGGL:
10081 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10082 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10085 case RENDERPATH_GL20:
10086 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10087 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10089 case RENDERPATH_GL13:
10090 case RENDERPATH_GL11:
10095 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10098 const msurface_t *surface;
10099 if (r_waterstate.renderingscene)
10101 for (i = 0;i < texturenumsurfaces;i++)
10103 surface = texturesurfacelist[i];
10104 RSurf_BindLightmapForSurface(surface);
10105 RSurf_BindReflectionForSurface(surface);
10106 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);
10110 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10114 const msurface_t *surface = texturesurfacelist[0];
10115 const msurface_t *surface2;
10120 if (texturenumsurfaces == 1)
10122 RSurf_BindLightmapForSurface(surface);
10123 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);
10125 else if (r_batchmode.integer == 2)
10127 #define MAXBATCHTRIANGLES 4096
10128 int batchtriangles = 0;
10129 static int batchelements[MAXBATCHTRIANGLES*3];
10130 for (i = 0;i < texturenumsurfaces;i = j)
10132 surface = texturesurfacelist[i];
10133 RSurf_BindLightmapForSurface(surface);
10135 if (surface->num_triangles > MAXBATCHTRIANGLES)
10137 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);
10140 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10141 batchtriangles = surface->num_triangles;
10142 firstvertex = surface->num_firstvertex;
10143 endvertex = surface->num_firstvertex + surface->num_vertices;
10144 for (;j < texturenumsurfaces;j++)
10146 surface2 = texturesurfacelist[j];
10147 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10149 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10150 batchtriangles += surface2->num_triangles;
10151 firstvertex = min(firstvertex, surface2->num_firstvertex);
10152 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10154 surface2 = texturesurfacelist[j-1];
10155 numvertices = endvertex - firstvertex;
10156 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10159 else if (r_batchmode.integer == 1)
10162 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10163 for (i = 0;i < texturenumsurfaces;i = j)
10165 surface = texturesurfacelist[i];
10166 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10167 if (texturesurfacelist[j] != surface2)
10169 Con_Printf(" %i", j - i);
10172 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10174 for (i = 0;i < texturenumsurfaces;i = j)
10176 surface = texturesurfacelist[i];
10177 RSurf_BindLightmapForSurface(surface);
10178 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10179 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10182 Con_Printf(" %i", j - i);
10184 surface2 = texturesurfacelist[j-1];
10185 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10186 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10187 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10195 for (i = 0;i < texturenumsurfaces;i++)
10197 surface = texturesurfacelist[i];
10198 RSurf_BindLightmapForSurface(surface);
10199 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);
10204 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10207 int texturesurfaceindex;
10208 if (r_showsurfaces.integer == 2)
10210 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10212 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10213 for (j = 0;j < surface->num_triangles;j++)
10215 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10216 GL_Color(f, f, f, 1);
10217 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10223 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10225 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10226 int k = (int)(((size_t)surface) / sizeof(msurface_t));
10227 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);
10228 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);
10233 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10235 int texturesurfaceindex;
10239 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10241 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10242 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)
10250 rsurface.lightmapcolor4f = rsurface.array_color4f;
10251 rsurface.lightmapcolor4f_bufferobject = 0;
10252 rsurface.lightmapcolor4f_bufferoffset = 0;
10255 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10257 int texturesurfaceindex;
10263 if (rsurface.lightmapcolor4f)
10265 // generate color arrays for the surfaces in this list
10266 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10268 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10269 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)
10271 f = RSurf_FogVertex(v);
10281 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10283 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10284 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)
10286 f = RSurf_FogVertex(v);
10294 rsurface.lightmapcolor4f = rsurface.array_color4f;
10295 rsurface.lightmapcolor4f_bufferobject = 0;
10296 rsurface.lightmapcolor4f_bufferoffset = 0;
10299 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10301 int texturesurfaceindex;
10307 if (!rsurface.lightmapcolor4f)
10309 // generate color arrays for the surfaces in this list
10310 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10312 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10313 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)
10315 f = RSurf_FogVertex(v);
10316 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10317 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10318 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10322 rsurface.lightmapcolor4f = rsurface.array_color4f;
10323 rsurface.lightmapcolor4f_bufferobject = 0;
10324 rsurface.lightmapcolor4f_bufferoffset = 0;
10327 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10329 int texturesurfaceindex;
10333 if (!rsurface.lightmapcolor4f)
10335 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10337 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10338 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)
10346 rsurface.lightmapcolor4f = rsurface.array_color4f;
10347 rsurface.lightmapcolor4f_bufferobject = 0;
10348 rsurface.lightmapcolor4f_bufferoffset = 0;
10351 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10353 int texturesurfaceindex;
10357 if (!rsurface.lightmapcolor4f)
10359 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10361 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10362 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)
10364 c2[0] = c[0] + r_refdef.scene.ambient;
10365 c2[1] = c[1] + r_refdef.scene.ambient;
10366 c2[2] = c[2] + r_refdef.scene.ambient;
10370 rsurface.lightmapcolor4f = rsurface.array_color4f;
10371 rsurface.lightmapcolor4f_bufferobject = 0;
10372 rsurface.lightmapcolor4f_bufferoffset = 0;
10375 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10378 rsurface.lightmapcolor4f = NULL;
10379 rsurface.lightmapcolor4f_bufferobject = 0;
10380 rsurface.lightmapcolor4f_bufferoffset = 0;
10381 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10382 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10383 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10384 GL_Color(r, g, b, a);
10385 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10388 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10390 // TODO: optimize applyfog && applycolor case
10391 // just apply fog if necessary, and tint the fog color array if necessary
10392 rsurface.lightmapcolor4f = NULL;
10393 rsurface.lightmapcolor4f_bufferobject = 0;
10394 rsurface.lightmapcolor4f_bufferoffset = 0;
10395 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10396 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10397 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10398 GL_Color(r, g, b, a);
10399 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10402 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10404 int texturesurfaceindex;
10408 if (texturesurfacelist[0]->lightmapinfo)
10410 // generate color arrays for the surfaces in this list
10411 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10413 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10414 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10416 if (surface->lightmapinfo->samples)
10418 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10419 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10420 VectorScale(lm, scale, c);
10421 if (surface->lightmapinfo->styles[1] != 255)
10423 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10425 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10426 VectorMA(c, scale, lm, c);
10427 if (surface->lightmapinfo->styles[2] != 255)
10430 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10431 VectorMA(c, scale, lm, c);
10432 if (surface->lightmapinfo->styles[3] != 255)
10435 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10436 VectorMA(c, scale, lm, c);
10446 rsurface.lightmapcolor4f = rsurface.array_color4f;
10447 rsurface.lightmapcolor4f_bufferobject = 0;
10448 rsurface.lightmapcolor4f_bufferoffset = 0;
10452 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10453 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10454 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10456 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10457 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10458 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10459 GL_Color(r, g, b, a);
10460 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10463 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10465 int texturesurfaceindex;
10472 vec3_t ambientcolor;
10473 vec3_t diffusecolor;
10477 VectorCopy(rsurface.modellight_lightdir, lightdir);
10478 f = 0.5f * r_refdef.lightmapintensity;
10479 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10480 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10481 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10482 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10483 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10484 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10486 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10488 // generate color arrays for the surfaces in this list
10489 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10491 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10492 int numverts = surface->num_vertices;
10493 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10494 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10495 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10496 // q3-style directional shading
10497 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10499 if ((f = DotProduct(n, lightdir)) > 0)
10500 VectorMA(ambientcolor, f, diffusecolor, c);
10502 VectorCopy(ambientcolor, c);
10510 rsurface.lightmapcolor4f = rsurface.array_color4f;
10511 rsurface.lightmapcolor4f_bufferobject = 0;
10512 rsurface.lightmapcolor4f_bufferoffset = 0;
10513 *applycolor = false;
10517 *r = ambientcolor[0];
10518 *g = ambientcolor[1];
10519 *b = ambientcolor[2];
10520 rsurface.lightmapcolor4f = NULL;
10521 rsurface.lightmapcolor4f_bufferobject = 0;
10522 rsurface.lightmapcolor4f_bufferoffset = 0;
10526 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10528 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10529 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10530 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10531 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10532 GL_Color(r, g, b, a);
10533 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10536 void RSurf_SetupDepthAndCulling(void)
10538 // submodels are biased to avoid z-fighting with world surfaces that they
10539 // may be exactly overlapping (avoids z-fighting artifacts on certain
10540 // doors and things in Quake maps)
10541 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10542 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10543 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10544 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10547 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10549 // transparent sky would be ridiculous
10550 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10552 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10553 skyrenderlater = true;
10554 RSurf_SetupDepthAndCulling();
10555 GL_DepthMask(true);
10556 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10557 // skymasking on them, and Quake3 never did sky masking (unlike
10558 // software Quake and software Quake2), so disable the sky masking
10559 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10560 // and skymasking also looks very bad when noclipping outside the
10561 // level, so don't use it then either.
10562 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10564 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10565 R_Mesh_ColorPointer(NULL, 0, 0);
10566 R_Mesh_ResetTextureState();
10567 if (skyrendermasked)
10569 R_SetupShader_DepthOrShadow();
10570 // depth-only (masking)
10571 GL_ColorMask(0,0,0,0);
10572 // just to make sure that braindead drivers don't draw
10573 // anything despite that colormask...
10574 GL_BlendFunc(GL_ZERO, GL_ONE);
10578 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10580 GL_BlendFunc(GL_ONE, GL_ZERO);
10582 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10583 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10584 if (skyrendermasked)
10585 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10587 R_Mesh_ResetTextureState();
10588 GL_Color(1, 1, 1, 1);
10591 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10592 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10593 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10595 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10597 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10600 // render screenspace normalmap to texture
10601 GL_DepthMask(true);
10602 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10603 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10605 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10607 // render water or distortion background, then blend surface on top
10608 GL_DepthMask(true);
10609 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10610 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10611 GL_DepthMask(false);
10612 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10613 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10614 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10616 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10620 // render surface normally
10621 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10622 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10623 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10624 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10625 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10626 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10628 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10632 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10634 // OpenGL 1.3 path - anything not completely ancient
10635 int texturesurfaceindex;
10636 qboolean applycolor;
10639 const texturelayer_t *layer;
10640 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10642 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10645 int layertexrgbscale;
10646 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10648 if (layerindex == 0)
10649 GL_AlphaTest(true);
10652 GL_AlphaTest(false);
10653 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10656 GL_DepthMask(layer->depthmask && writedepth);
10657 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10658 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10660 layertexrgbscale = 4;
10661 VectorScale(layer->color, 0.25f, layercolor);
10663 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10665 layertexrgbscale = 2;
10666 VectorScale(layer->color, 0.5f, layercolor);
10670 layertexrgbscale = 1;
10671 VectorScale(layer->color, 1.0f, layercolor);
10673 layercolor[3] = layer->color[3];
10674 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10675 R_Mesh_ColorPointer(NULL, 0, 0);
10676 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10677 switch (layer->type)
10679 case TEXTURELAYERTYPE_LITTEXTURE:
10680 // single-pass lightmapped texture with 2x rgbscale
10681 R_Mesh_TexBind(0, r_texture_white);
10682 R_Mesh_TexMatrix(0, NULL);
10683 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10684 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10685 R_Mesh_TexBind(1, layer->texture);
10686 R_Mesh_TexMatrix(1, &layer->texmatrix);
10687 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10688 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10689 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10690 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10691 else if (rsurface.uselightmaptexture)
10692 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10694 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10696 case TEXTURELAYERTYPE_TEXTURE:
10697 // singletexture unlit texture with transparency support
10698 R_Mesh_TexBind(0, layer->texture);
10699 R_Mesh_TexMatrix(0, &layer->texmatrix);
10700 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10701 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10702 R_Mesh_TexBind(1, 0);
10703 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10704 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10706 case TEXTURELAYERTYPE_FOG:
10707 // singletexture fogging
10708 if (layer->texture)
10710 R_Mesh_TexBind(0, layer->texture);
10711 R_Mesh_TexMatrix(0, &layer->texmatrix);
10712 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10713 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10717 R_Mesh_TexBind(0, 0);
10718 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10720 R_Mesh_TexBind(1, 0);
10721 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10722 // generate a color array for the fog pass
10723 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10724 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10730 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10731 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)
10733 f = 1 - RSurf_FogVertex(v);
10734 c[0] = layercolor[0];
10735 c[1] = layercolor[1];
10736 c[2] = layercolor[2];
10737 c[3] = f * layercolor[3];
10740 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10743 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10747 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10749 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10750 GL_AlphaTest(false);
10754 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10756 // OpenGL 1.1 - crusty old voodoo path
10757 int texturesurfaceindex;
10760 const texturelayer_t *layer;
10761 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10763 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10765 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10767 if (layerindex == 0)
10768 GL_AlphaTest(true);
10771 GL_AlphaTest(false);
10772 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10775 GL_DepthMask(layer->depthmask && writedepth);
10776 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10777 R_Mesh_ColorPointer(NULL, 0, 0);
10778 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10779 switch (layer->type)
10781 case TEXTURELAYERTYPE_LITTEXTURE:
10782 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10784 // two-pass lit texture with 2x rgbscale
10785 // first the lightmap pass
10786 R_Mesh_TexBind(0, r_texture_white);
10787 R_Mesh_TexMatrix(0, NULL);
10788 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10789 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10790 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10791 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10792 else if (rsurface.uselightmaptexture)
10793 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10795 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10796 // then apply the texture to it
10797 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10798 R_Mesh_TexBind(0, layer->texture);
10799 R_Mesh_TexMatrix(0, &layer->texmatrix);
10800 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10801 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10802 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);
10806 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10807 R_Mesh_TexBind(0, layer->texture);
10808 R_Mesh_TexMatrix(0, &layer->texmatrix);
10809 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10810 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10811 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10812 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);
10814 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);
10817 case TEXTURELAYERTYPE_TEXTURE:
10818 // singletexture unlit texture with transparency support
10819 R_Mesh_TexBind(0, layer->texture);
10820 R_Mesh_TexMatrix(0, &layer->texmatrix);
10821 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10822 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10823 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);
10825 case TEXTURELAYERTYPE_FOG:
10826 // singletexture fogging
10827 if (layer->texture)
10829 R_Mesh_TexBind(0, layer->texture);
10830 R_Mesh_TexMatrix(0, &layer->texmatrix);
10831 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10832 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10836 R_Mesh_TexBind(0, 0);
10837 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10839 // generate a color array for the fog pass
10840 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10841 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10847 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10848 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)
10850 f = 1 - RSurf_FogVertex(v);
10851 c[0] = layer->color[0];
10852 c[1] = layer->color[1];
10853 c[2] = layer->color[2];
10854 c[3] = f * layer->color[3];
10857 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10860 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10864 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10866 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10867 GL_AlphaTest(false);
10871 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10875 GL_AlphaTest(false);
10876 R_Mesh_ColorPointer(NULL, 0, 0);
10877 R_Mesh_ResetTextureState();
10878 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10880 if(rsurface.texture && rsurface.texture->currentskinframe)
10882 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10883 c[3] *= rsurface.texture->currentalpha;
10893 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10895 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10896 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10897 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10900 // brighten it up (as texture value 127 means "unlit")
10901 c[0] *= 2 * r_refdef.view.colorscale;
10902 c[1] *= 2 * r_refdef.view.colorscale;
10903 c[2] *= 2 * r_refdef.view.colorscale;
10905 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10906 c[3] *= r_wateralpha.value;
10908 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10910 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10911 GL_DepthMask(false);
10913 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10915 GL_BlendFunc(GL_ONE, GL_ONE);
10916 GL_DepthMask(false);
10918 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10920 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10921 GL_DepthMask(false);
10923 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10925 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10926 GL_DepthMask(false);
10930 GL_BlendFunc(GL_ONE, GL_ZERO);
10931 GL_DepthMask(writedepth);
10934 rsurface.lightmapcolor4f = NULL;
10936 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10938 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10940 rsurface.lightmapcolor4f = NULL;
10941 rsurface.lightmapcolor4f_bufferobject = 0;
10942 rsurface.lightmapcolor4f_bufferoffset = 0;
10944 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10946 qboolean applycolor = true;
10949 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10951 r_refdef.lightmapintensity = 1;
10952 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10953 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10957 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10959 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10960 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10961 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10964 if(!rsurface.lightmapcolor4f)
10965 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10967 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10968 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10969 if(r_refdef.fogenabled)
10970 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10972 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10973 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10976 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10979 RSurf_SetupDepthAndCulling();
10980 if (r_showsurfaces.integer == 3 && !prepass)
10982 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10985 switch (vid.renderpath)
10987 case RENDERPATH_GL20:
10988 case RENDERPATH_CGGL:
10989 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10991 case RENDERPATH_GL13:
10992 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10994 case RENDERPATH_GL11:
10995 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11001 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11004 RSurf_SetupDepthAndCulling();
11005 if (r_showsurfaces.integer == 3 && !prepass)
11007 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11010 switch (vid.renderpath)
11012 case RENDERPATH_GL20:
11013 case RENDERPATH_CGGL:
11014 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11016 case RENDERPATH_GL13:
11017 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11019 case RENDERPATH_GL11:
11020 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11026 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11029 int texturenumsurfaces, endsurface;
11030 texture_t *texture;
11031 const msurface_t *surface;
11032 const msurface_t *texturesurfacelist[256];
11034 // if the model is static it doesn't matter what value we give for
11035 // wantnormals and wanttangents, so this logic uses only rules applicable
11036 // to a model, knowing that they are meaningless otherwise
11037 if (ent == r_refdef.scene.worldentity)
11038 RSurf_ActiveWorldEntity();
11039 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11040 RSurf_ActiveModelEntity(ent, false, false, false);
11043 switch (vid.renderpath)
11045 case RENDERPATH_GL20:
11046 case RENDERPATH_CGGL:
11047 RSurf_ActiveModelEntity(ent, true, true, false);
11049 case RENDERPATH_GL13:
11050 case RENDERPATH_GL11:
11051 RSurf_ActiveModelEntity(ent, true, false, false);
11056 if (r_transparentdepthmasking.integer)
11058 qboolean setup = false;
11059 for (i = 0;i < numsurfaces;i = j)
11062 surface = rsurface.modelsurfaces + surfacelist[i];
11063 texture = surface->texture;
11064 rsurface.texture = R_GetCurrentTexture(texture);
11065 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11066 // scan ahead until we find a different texture
11067 endsurface = min(i + 1024, numsurfaces);
11068 texturenumsurfaces = 0;
11069 texturesurfacelist[texturenumsurfaces++] = surface;
11070 for (;j < endsurface;j++)
11072 surface = rsurface.modelsurfaces + surfacelist[j];
11073 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11075 texturesurfacelist[texturenumsurfaces++] = surface;
11077 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11079 // render the range of surfaces as depth
11083 GL_ColorMask(0,0,0,0);
11085 GL_DepthTest(true);
11086 GL_BlendFunc(GL_ONE, GL_ZERO);
11087 GL_DepthMask(true);
11088 GL_AlphaTest(false);
11089 R_Mesh_ColorPointer(NULL, 0, 0);
11090 R_Mesh_ResetTextureState();
11091 R_SetupShader_DepthOrShadow();
11093 RSurf_SetupDepthAndCulling();
11094 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11095 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11098 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11101 for (i = 0;i < numsurfaces;i = j)
11104 surface = rsurface.modelsurfaces + surfacelist[i];
11105 texture = surface->texture;
11106 rsurface.texture = R_GetCurrentTexture(texture);
11107 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11108 // scan ahead until we find a different texture
11109 endsurface = min(i + 1024, numsurfaces);
11110 texturenumsurfaces = 0;
11111 texturesurfacelist[texturenumsurfaces++] = surface;
11112 for (;j < endsurface;j++)
11114 surface = rsurface.modelsurfaces + surfacelist[j];
11115 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11117 texturesurfacelist[texturenumsurfaces++] = surface;
11119 // render the range of surfaces
11120 if (ent == r_refdef.scene.worldentity)
11121 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11123 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11125 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11126 GL_AlphaTest(false);
11129 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11131 // transparent surfaces get pushed off into the transparent queue
11132 int surfacelistindex;
11133 const msurface_t *surface;
11134 vec3_t tempcenter, center;
11135 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11137 surface = texturesurfacelist[surfacelistindex];
11138 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11139 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11140 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11141 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11142 if (queueentity->transparent_offset) // transparent offset
11144 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11145 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11146 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11148 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11152 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11154 const entity_render_t *queueentity = r_refdef.scene.worldentity;
11158 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11160 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11162 RSurf_SetupDepthAndCulling();
11163 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11164 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11168 if (!rsurface.texture->currentnumlayers)
11170 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11171 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11173 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11175 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11177 RSurf_SetupDepthAndCulling();
11178 GL_AlphaTest(false);
11179 R_Mesh_ColorPointer(NULL, 0, 0);
11180 R_Mesh_ResetTextureState();
11181 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11182 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11183 GL_DepthMask(true);
11184 GL_BlendFunc(GL_ONE, GL_ZERO);
11185 GL_Color(0, 0, 0, 1);
11186 GL_DepthTest(writedepth);
11187 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11189 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11191 RSurf_SetupDepthAndCulling();
11192 GL_AlphaTest(false);
11193 R_Mesh_ColorPointer(NULL, 0, 0);
11194 R_Mesh_ResetTextureState();
11195 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11196 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11197 GL_DepthMask(true);
11198 GL_BlendFunc(GL_ONE, GL_ZERO);
11199 GL_DepthTest(true);
11200 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11202 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11203 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11204 else if (!rsurface.texture->currentnumlayers)
11206 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11208 // in the deferred case, transparent surfaces were queued during prepass
11209 if (!r_shadow_usingdeferredprepass)
11210 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11214 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11215 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11220 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11223 texture_t *texture;
11224 // break the surface list down into batches by texture and use of lightmapping
11225 for (i = 0;i < numsurfaces;i = j)
11228 // texture is the base texture pointer, rsurface.texture is the
11229 // current frame/skin the texture is directing us to use (for example
11230 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11231 // use skin 1 instead)
11232 texture = surfacelist[i]->texture;
11233 rsurface.texture = R_GetCurrentTexture(texture);
11234 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11235 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11237 // if this texture is not the kind we want, skip ahead to the next one
11238 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11242 // simply scan ahead until we find a different texture or lightmap state
11243 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11245 // render the range of surfaces
11246 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11250 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11255 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11257 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11259 RSurf_SetupDepthAndCulling();
11260 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11261 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11265 if (!rsurface.texture->currentnumlayers)
11267 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11268 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11270 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11272 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11274 RSurf_SetupDepthAndCulling();
11275 GL_AlphaTest(false);
11276 R_Mesh_ColorPointer(NULL, 0, 0);
11277 R_Mesh_ResetTextureState();
11278 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11279 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11280 GL_DepthMask(true);
11281 GL_BlendFunc(GL_ONE, GL_ZERO);
11282 GL_Color(0, 0, 0, 1);
11283 GL_DepthTest(writedepth);
11284 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11286 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11288 RSurf_SetupDepthAndCulling();
11289 GL_AlphaTest(false);
11290 R_Mesh_ColorPointer(NULL, 0, 0);
11291 R_Mesh_ResetTextureState();
11292 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11293 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11294 GL_DepthMask(true);
11295 GL_BlendFunc(GL_ONE, GL_ZERO);
11296 GL_DepthTest(true);
11297 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11299 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11300 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11301 else if (!rsurface.texture->currentnumlayers)
11303 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11305 // in the deferred case, transparent surfaces were queued during prepass
11306 if (!r_shadow_usingdeferredprepass)
11307 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11311 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11312 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11317 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11320 texture_t *texture;
11321 // break the surface list down into batches by texture and use of lightmapping
11322 for (i = 0;i < numsurfaces;i = j)
11325 // texture is the base texture pointer, rsurface.texture is the
11326 // current frame/skin the texture is directing us to use (for example
11327 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11328 // use skin 1 instead)
11329 texture = surfacelist[i]->texture;
11330 rsurface.texture = R_GetCurrentTexture(texture);
11331 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11332 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11334 // if this texture is not the kind we want, skip ahead to the next one
11335 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11339 // simply scan ahead until we find a different texture or lightmap state
11340 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11342 // render the range of surfaces
11343 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11347 float locboxvertex3f[6*4*3] =
11349 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11350 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11351 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11352 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11353 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11354 1,0,0, 0,0,0, 0,1,0, 1,1,0
11357 unsigned short locboxelements[6*2*3] =
11362 12,13,14, 12,14,15,
11363 16,17,18, 16,18,19,
11367 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11370 cl_locnode_t *loc = (cl_locnode_t *)ent;
11372 float vertex3f[6*4*3];
11374 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11375 GL_DepthMask(false);
11376 GL_DepthRange(0, 1);
11377 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11378 GL_DepthTest(true);
11379 GL_CullFace(GL_NONE);
11380 R_EntityMatrix(&identitymatrix);
11382 R_Mesh_VertexPointer(vertex3f, 0, 0);
11383 R_Mesh_ColorPointer(NULL, 0, 0);
11384 R_Mesh_ResetTextureState();
11385 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11387 i = surfacelist[0];
11388 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11389 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11390 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11391 surfacelist[0] < 0 ? 0.5f : 0.125f);
11393 if (VectorCompare(loc->mins, loc->maxs))
11395 VectorSet(size, 2, 2, 2);
11396 VectorMA(loc->mins, -0.5f, size, mins);
11400 VectorCopy(loc->mins, mins);
11401 VectorSubtract(loc->maxs, loc->mins, size);
11404 for (i = 0;i < 6*4*3;)
11405 for (j = 0;j < 3;j++, i++)
11406 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11408 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11411 void R_DrawLocs(void)
11414 cl_locnode_t *loc, *nearestloc;
11416 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11417 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11419 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11420 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11424 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11426 if (decalsystem->decals)
11427 Mem_Free(decalsystem->decals);
11428 memset(decalsystem, 0, sizeof(*decalsystem));
11431 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)
11434 tridecal_t *decals;
11437 // expand or initialize the system
11438 if (decalsystem->maxdecals <= decalsystem->numdecals)
11440 decalsystem_t old = *decalsystem;
11441 qboolean useshortelements;
11442 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11443 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11444 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)));
11445 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11446 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11447 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11448 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11449 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11450 if (decalsystem->numdecals)
11451 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11453 Mem_Free(old.decals);
11454 for (i = 0;i < decalsystem->maxdecals*3;i++)
11455 decalsystem->element3i[i] = i;
11456 if (useshortelements)
11457 for (i = 0;i < decalsystem->maxdecals*3;i++)
11458 decalsystem->element3s[i] = i;
11461 // grab a decal and search for another free slot for the next one
11462 decals = decalsystem->decals;
11463 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11464 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11466 decalsystem->freedecal = i;
11467 if (decalsystem->numdecals <= i)
11468 decalsystem->numdecals = i + 1;
11470 // initialize the decal
11472 decal->triangleindex = triangleindex;
11473 decal->surfaceindex = surfaceindex;
11474 decal->decalsequence = decalsequence;
11475 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11476 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11477 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11478 decal->color4ub[0][3] = 255;
11479 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11480 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11481 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11482 decal->color4ub[1][3] = 255;
11483 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11484 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11485 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11486 decal->color4ub[2][3] = 255;
11487 decal->vertex3f[0][0] = v0[0];
11488 decal->vertex3f[0][1] = v0[1];
11489 decal->vertex3f[0][2] = v0[2];
11490 decal->vertex3f[1][0] = v1[0];
11491 decal->vertex3f[1][1] = v1[1];
11492 decal->vertex3f[1][2] = v1[2];
11493 decal->vertex3f[2][0] = v2[0];
11494 decal->vertex3f[2][1] = v2[1];
11495 decal->vertex3f[2][2] = v2[2];
11496 decal->texcoord2f[0][0] = t0[0];
11497 decal->texcoord2f[0][1] = t0[1];
11498 decal->texcoord2f[1][0] = t1[0];
11499 decal->texcoord2f[1][1] = t1[1];
11500 decal->texcoord2f[2][0] = t2[0];
11501 decal->texcoord2f[2][1] = t2[1];
11504 extern cvar_t cl_decals_bias;
11505 extern cvar_t cl_decals_models;
11506 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11507 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)
11509 matrix4x4_t projection;
11510 decalsystem_t *decalsystem;
11513 const float *vertex3f;
11514 const msurface_t *surface;
11515 const msurface_t *surfaces;
11516 const int *surfacelist;
11517 const texture_t *texture;
11519 int numsurfacelist;
11520 int surfacelistindex;
11527 float localorigin[3];
11528 float localnormal[3];
11529 float localmins[3];
11530 float localmaxs[3];
11536 float planes[6][4];
11538 float points[2][9][3];
11542 decalsystem = &ent->decalsystem;
11543 model = ent->model;
11544 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11546 R_DecalSystem_Reset(&ent->decalsystem);
11550 if (!model->brush.data_nodes && !cl_decals_models.integer)
11552 if (decalsystem->model)
11553 R_DecalSystem_Reset(decalsystem);
11557 if (decalsystem->model != model)
11558 R_DecalSystem_Reset(decalsystem);
11559 decalsystem->model = model;
11561 RSurf_ActiveModelEntity(ent, false, false, false);
11563 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11564 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11565 VectorNormalize(localnormal);
11566 localsize = worldsize*rsurface.inversematrixscale;
11567 localmins[0] = localorigin[0] - localsize;
11568 localmins[1] = localorigin[1] - localsize;
11569 localmins[2] = localorigin[2] - localsize;
11570 localmaxs[0] = localorigin[0] + localsize;
11571 localmaxs[1] = localorigin[1] + localsize;
11572 localmaxs[2] = localorigin[2] + localsize;
11574 //VectorCopy(localnormal, planes[4]);
11575 //VectorVectors(planes[4], planes[2], planes[0]);
11576 AnglesFromVectors(angles, localnormal, NULL, false);
11577 AngleVectors(angles, planes[0], planes[2], planes[4]);
11578 VectorNegate(planes[0], planes[1]);
11579 VectorNegate(planes[2], planes[3]);
11580 VectorNegate(planes[4], planes[5]);
11581 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11582 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11583 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11584 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11585 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11586 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11591 matrix4x4_t forwardprojection;
11592 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11593 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11598 float projectionvector[4][3];
11599 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11600 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11601 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11602 projectionvector[0][0] = planes[0][0] * ilocalsize;
11603 projectionvector[0][1] = planes[1][0] * ilocalsize;
11604 projectionvector[0][2] = planes[2][0] * ilocalsize;
11605 projectionvector[1][0] = planes[0][1] * ilocalsize;
11606 projectionvector[1][1] = planes[1][1] * ilocalsize;
11607 projectionvector[1][2] = planes[2][1] * ilocalsize;
11608 projectionvector[2][0] = planes[0][2] * ilocalsize;
11609 projectionvector[2][1] = planes[1][2] * ilocalsize;
11610 projectionvector[2][2] = planes[2][2] * ilocalsize;
11611 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11612 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11613 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11614 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11618 dynamic = model->surfmesh.isanimated;
11619 vertex3f = rsurface.modelvertex3f;
11620 numsurfacelist = model->nummodelsurfaces;
11621 surfacelist = model->sortedmodelsurfaces;
11622 surfaces = model->data_surfaces;
11623 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11625 surfaceindex = surfacelist[surfacelistindex];
11626 surface = surfaces + surfaceindex;
11627 // check cull box first because it rejects more than any other check
11628 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11630 // skip transparent surfaces
11631 texture = surface->texture;
11632 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11634 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11636 numtriangles = surface->num_triangles;
11637 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11639 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11641 index = 3*e[cornerindex];
11642 VectorCopy(vertex3f + index, v[cornerindex]);
11645 //TriangleNormal(v[0], v[1], v[2], normal);
11646 //if (DotProduct(normal, localnormal) < 0.0f)
11648 // clip by each of the box planes formed from the projection matrix
11649 // if anything survives, we emit the decal
11650 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]);
11653 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]);
11656 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]);
11659 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]);
11662 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]);
11665 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]);
11668 // some part of the triangle survived, so we have to accept it...
11671 // dynamic always uses the original triangle
11673 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11675 index = 3*e[cornerindex];
11676 VectorCopy(vertex3f + index, v[cornerindex]);
11679 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11681 // convert vertex positions to texcoords
11682 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11683 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11684 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11685 // calculate distance fade from the projection origin
11686 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11687 f = bound(0.0f, f, 1.0f);
11688 c[cornerindex][0] = r * f;
11689 c[cornerindex][1] = g * f;
11690 c[cornerindex][2] = b * f;
11691 c[cornerindex][3] = 1.0f;
11692 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11695 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);
11697 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11698 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);
11703 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11704 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)
11706 int renderentityindex;
11707 float worldmins[3];
11708 float worldmaxs[3];
11709 entity_render_t *ent;
11711 if (!cl_decals_newsystem.integer)
11714 worldmins[0] = worldorigin[0] - worldsize;
11715 worldmins[1] = worldorigin[1] - worldsize;
11716 worldmins[2] = worldorigin[2] - worldsize;
11717 worldmaxs[0] = worldorigin[0] + worldsize;
11718 worldmaxs[1] = worldorigin[1] + worldsize;
11719 worldmaxs[2] = worldorigin[2] + worldsize;
11721 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11723 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11725 ent = r_refdef.scene.entities[renderentityindex];
11726 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11729 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11733 typedef struct r_decalsystem_splatqueue_s
11735 vec3_t worldorigin;
11736 vec3_t worldnormal;
11742 r_decalsystem_splatqueue_t;
11744 int r_decalsystem_numqueued = 0;
11745 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11747 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)
11749 r_decalsystem_splatqueue_t *queue;
11751 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11754 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11755 VectorCopy(worldorigin, queue->worldorigin);
11756 VectorCopy(worldnormal, queue->worldnormal);
11757 Vector4Set(queue->color, r, g, b, a);
11758 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11759 queue->worldsize = worldsize;
11760 queue->decalsequence = cl.decalsequence++;
11763 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11766 r_decalsystem_splatqueue_t *queue;
11768 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11769 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);
11770 r_decalsystem_numqueued = 0;
11773 extern cvar_t cl_decals_max;
11774 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11777 decalsystem_t *decalsystem = &ent->decalsystem;
11784 if (!decalsystem->numdecals)
11787 if (r_showsurfaces.integer)
11790 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11792 R_DecalSystem_Reset(decalsystem);
11796 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11797 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11799 if (decalsystem->lastupdatetime)
11800 frametime = (cl.time - decalsystem->lastupdatetime);
11803 decalsystem->lastupdatetime = cl.time;
11804 decal = decalsystem->decals;
11805 numdecals = decalsystem->numdecals;
11807 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11809 if (decal->color4ub[0][3])
11811 decal->lived += frametime;
11812 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11814 memset(decal, 0, sizeof(*decal));
11815 if (decalsystem->freedecal > i)
11816 decalsystem->freedecal = i;
11820 decal = decalsystem->decals;
11821 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11824 // collapse the array by shuffling the tail decals into the gaps
11827 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11828 decalsystem->freedecal++;
11829 if (decalsystem->freedecal == numdecals)
11831 decal[decalsystem->freedecal] = decal[--numdecals];
11834 decalsystem->numdecals = numdecals;
11836 if (numdecals <= 0)
11838 // if there are no decals left, reset decalsystem
11839 R_DecalSystem_Reset(decalsystem);
11843 extern skinframe_t *decalskinframe;
11844 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11847 decalsystem_t *decalsystem = &ent->decalsystem;
11856 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11859 numdecals = decalsystem->numdecals;
11863 if (r_showsurfaces.integer)
11866 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11868 R_DecalSystem_Reset(decalsystem);
11872 // if the model is static it doesn't matter what value we give for
11873 // wantnormals and wanttangents, so this logic uses only rules applicable
11874 // to a model, knowing that they are meaningless otherwise
11875 if (ent == r_refdef.scene.worldentity)
11876 RSurf_ActiveWorldEntity();
11878 RSurf_ActiveModelEntity(ent, false, false, false);
11880 decalsystem->lastupdatetime = cl.time;
11881 decal = decalsystem->decals;
11883 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11885 // update vertex positions for animated models
11886 v3f = decalsystem->vertex3f;
11887 c4f = decalsystem->color4f;
11888 t2f = decalsystem->texcoord2f;
11889 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11891 if (!decal->color4ub[0][3])
11894 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11897 // update color values for fading decals
11898 if (decal->lived >= cl_decals_time.value)
11900 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11901 alpha *= (1.0f/255.0f);
11904 alpha = 1.0f/255.0f;
11906 c4f[ 0] = decal->color4ub[0][0] * alpha;
11907 c4f[ 1] = decal->color4ub[0][1] * alpha;
11908 c4f[ 2] = decal->color4ub[0][2] * alpha;
11910 c4f[ 4] = decal->color4ub[1][0] * alpha;
11911 c4f[ 5] = decal->color4ub[1][1] * alpha;
11912 c4f[ 6] = decal->color4ub[1][2] * alpha;
11914 c4f[ 8] = decal->color4ub[2][0] * alpha;
11915 c4f[ 9] = decal->color4ub[2][1] * alpha;
11916 c4f[10] = decal->color4ub[2][2] * alpha;
11919 t2f[0] = decal->texcoord2f[0][0];
11920 t2f[1] = decal->texcoord2f[0][1];
11921 t2f[2] = decal->texcoord2f[1][0];
11922 t2f[3] = decal->texcoord2f[1][1];
11923 t2f[4] = decal->texcoord2f[2][0];
11924 t2f[5] = decal->texcoord2f[2][1];
11926 // update vertex positions for animated models
11927 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11929 e = rsurface.modelelement3i + 3*decal->triangleindex;
11930 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11931 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11932 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11936 VectorCopy(decal->vertex3f[0], v3f);
11937 VectorCopy(decal->vertex3f[1], v3f + 3);
11938 VectorCopy(decal->vertex3f[2], v3f + 6);
11949 r_refdef.stats.drawndecals += numtris;
11951 if (r_refdef.fogenabled)
11953 switch(vid.renderpath)
11955 case RENDERPATH_GL20:
11956 case RENDERPATH_CGGL:
11957 case RENDERPATH_GL13:
11958 case RENDERPATH_GL11:
11959 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11961 alpha = RSurf_FogVertex(v3f);
11970 // now render the decals all at once
11971 // (this assumes they all use one particle font texture!)
11972 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);
11973 R_Mesh_ResetTextureState();
11974 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11975 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11976 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11977 GL_DepthMask(false);
11978 GL_DepthRange(0, 1);
11979 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11980 GL_DepthTest(true);
11981 GL_CullFace(GL_NONE);
11982 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11983 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11984 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11988 static void R_DrawModelDecals(void)
11992 // fade faster when there are too many decals
11993 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11994 for (i = 0;i < r_refdef.scene.numentities;i++)
11995 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11997 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11998 for (i = 0;i < r_refdef.scene.numentities;i++)
11999 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12000 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12002 R_DecalSystem_ApplySplatEntitiesQueue();
12004 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12005 for (i = 0;i < r_refdef.scene.numentities;i++)
12006 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12008 r_refdef.stats.totaldecals += numdecals;
12010 if (r_showsurfaces.integer)
12013 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12015 for (i = 0;i < r_refdef.scene.numentities;i++)
12017 if (!r_refdef.viewcache.entityvisible[i])
12019 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12020 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12024 void R_DrawDebugModel(void)
12026 entity_render_t *ent = rsurface.entity;
12027 int i, j, k, l, flagsmask;
12029 const msurface_t *surface;
12030 dp_model_t *model = ent->model;
12033 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12035 R_Mesh_ColorPointer(NULL, 0, 0);
12036 R_Mesh_ResetTextureState();
12037 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12038 GL_DepthRange(0, 1);
12039 GL_DepthTest(!r_showdisabledepthtest.integer);
12040 GL_DepthMask(false);
12041 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12043 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
12045 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12046 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
12048 if (brush->colbrushf && brush->colbrushf->numtriangles)
12050 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12051 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);
12052 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12055 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
12057 if (surface->num_collisiontriangles)
12059 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
12060 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);
12061 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
12066 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12068 if (r_showtris.integer || r_shownormals.integer)
12070 if (r_showdisabledepthtest.integer)
12072 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12073 GL_DepthMask(false);
12077 GL_BlendFunc(GL_ONE, GL_ZERO);
12078 GL_DepthMask(true);
12080 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12082 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12084 rsurface.texture = R_GetCurrentTexture(surface->texture);
12085 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12087 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12088 if (r_showtris.value > 0)
12090 if (!rsurface.texture->currentlayers->depthmask)
12091 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12092 else if (ent == r_refdef.scene.worldentity)
12093 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12095 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12096 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12097 R_Mesh_ColorPointer(NULL, 0, 0);
12098 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12099 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12100 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12101 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);
12102 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12105 if (r_shownormals.value < 0)
12107 qglBegin(GL_LINES);
12108 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12110 VectorCopy(rsurface.vertex3f + l * 3, v);
12111 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12112 qglVertex3f(v[0], v[1], v[2]);
12113 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12114 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12115 qglVertex3f(v[0], v[1], v[2]);
12120 if (r_shownormals.value > 0)
12122 qglBegin(GL_LINES);
12123 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12125 VectorCopy(rsurface.vertex3f + l * 3, v);
12126 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12127 qglVertex3f(v[0], v[1], v[2]);
12128 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12129 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12130 qglVertex3f(v[0], v[1], v[2]);
12134 qglBegin(GL_LINES);
12135 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12137 VectorCopy(rsurface.vertex3f + l * 3, v);
12138 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12139 qglVertex3f(v[0], v[1], v[2]);
12140 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12141 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12142 qglVertex3f(v[0], v[1], v[2]);
12146 qglBegin(GL_LINES);
12147 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12149 VectorCopy(rsurface.vertex3f + l * 3, v);
12150 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12151 qglVertex3f(v[0], v[1], v[2]);
12152 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12153 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12154 qglVertex3f(v[0], v[1], v[2]);
12161 rsurface.texture = NULL;
12165 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12166 int r_maxsurfacelist = 0;
12167 const msurface_t **r_surfacelist = NULL;
12168 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12170 int i, j, endj, flagsmask;
12171 dp_model_t *model = r_refdef.scene.worldmodel;
12172 msurface_t *surfaces;
12173 unsigned char *update;
12174 int numsurfacelist = 0;
12178 if (r_maxsurfacelist < model->num_surfaces)
12180 r_maxsurfacelist = model->num_surfaces;
12182 Mem_Free((msurface_t**)r_surfacelist);
12183 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12186 RSurf_ActiveWorldEntity();
12188 surfaces = model->data_surfaces;
12189 update = model->brushq1.lightmapupdateflags;
12191 // update light styles on this submodel
12192 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12194 model_brush_lightstyleinfo_t *style;
12195 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12197 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12199 int *list = style->surfacelist;
12200 style->value = r_refdef.scene.lightstylevalue[style->style];
12201 for (j = 0;j < style->numsurfaces;j++)
12202 update[list[j]] = true;
12207 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12211 R_DrawDebugModel();
12212 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12216 rsurface.uselightmaptexture = false;
12217 rsurface.texture = NULL;
12218 rsurface.rtlight = NULL;
12219 numsurfacelist = 0;
12220 // add visible surfaces to draw list
12221 for (i = 0;i < model->nummodelsurfaces;i++)
12223 j = model->sortedmodelsurfaces[i];
12224 if (r_refdef.viewcache.world_surfacevisible[j])
12225 r_surfacelist[numsurfacelist++] = surfaces + j;
12227 // update lightmaps if needed
12228 if (model->brushq1.firstrender)
12230 model->brushq1.firstrender = false;
12231 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12233 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12237 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12238 if (r_refdef.viewcache.world_surfacevisible[j])
12240 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12242 // don't do anything if there were no surfaces
12243 if (!numsurfacelist)
12245 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12248 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12249 GL_AlphaTest(false);
12251 // add to stats if desired
12252 if (r_speeds.integer && !skysurfaces && !depthonly)
12254 r_refdef.stats.world_surfaces += numsurfacelist;
12255 for (j = 0;j < numsurfacelist;j++)
12256 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12259 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12262 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12264 int i, j, endj, flagsmask;
12265 dp_model_t *model = ent->model;
12266 msurface_t *surfaces;
12267 unsigned char *update;
12268 int numsurfacelist = 0;
12272 if (r_maxsurfacelist < model->num_surfaces)
12274 r_maxsurfacelist = model->num_surfaces;
12276 Mem_Free((msurface_t **)r_surfacelist);
12277 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12280 // if the model is static it doesn't matter what value we give for
12281 // wantnormals and wanttangents, so this logic uses only rules applicable
12282 // to a model, knowing that they are meaningless otherwise
12283 if (ent == r_refdef.scene.worldentity)
12284 RSurf_ActiveWorldEntity();
12285 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12286 RSurf_ActiveModelEntity(ent, false, false, false);
12288 RSurf_ActiveModelEntity(ent, true, true, true);
12289 else if (depthonly)
12290 RSurf_ActiveModelEntity(ent, false, false, false);
12293 switch (vid.renderpath)
12295 case RENDERPATH_GL20:
12296 case RENDERPATH_CGGL:
12297 RSurf_ActiveModelEntity(ent, true, true, false);
12299 case RENDERPATH_GL13:
12300 case RENDERPATH_GL11:
12301 RSurf_ActiveModelEntity(ent, true, false, false);
12306 surfaces = model->data_surfaces;
12307 update = model->brushq1.lightmapupdateflags;
12309 // update light styles
12310 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12312 model_brush_lightstyleinfo_t *style;
12313 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12315 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12317 int *list = style->surfacelist;
12318 style->value = r_refdef.scene.lightstylevalue[style->style];
12319 for (j = 0;j < style->numsurfaces;j++)
12320 update[list[j]] = true;
12325 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12329 R_DrawDebugModel();
12330 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12334 rsurface.uselightmaptexture = false;
12335 rsurface.texture = NULL;
12336 rsurface.rtlight = NULL;
12337 numsurfacelist = 0;
12338 // add visible surfaces to draw list
12339 for (i = 0;i < model->nummodelsurfaces;i++)
12340 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12341 // don't do anything if there were no surfaces
12342 if (!numsurfacelist)
12344 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12347 // update lightmaps if needed
12351 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12356 R_BuildLightMap(ent, surfaces + j);
12361 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12363 R_BuildLightMap(ent, surfaces + j);
12364 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12365 GL_AlphaTest(false);
12367 // add to stats if desired
12368 if (r_speeds.integer && !skysurfaces && !depthonly)
12370 r_refdef.stats.entities_surfaces += numsurfacelist;
12371 for (j = 0;j < numsurfacelist;j++)
12372 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12375 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12378 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12380 static texture_t texture;
12381 static msurface_t surface;
12382 const msurface_t *surfacelist = &surface;
12384 // fake enough texture and surface state to render this geometry
12386 texture.update_lastrenderframe = -1; // regenerate this texture
12387 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12388 texture.currentskinframe = skinframe;
12389 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12390 texture.specularscalemod = 1;
12391 texture.specularpowermod = 1;
12393 surface.texture = &texture;
12394 surface.num_triangles = numtriangles;
12395 surface.num_firsttriangle = firsttriangle;
12396 surface.num_vertices = numvertices;
12397 surface.num_firstvertex = firstvertex;
12400 rsurface.texture = R_GetCurrentTexture(surface.texture);
12401 rsurface.uselightmaptexture = false;
12402 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12405 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)
12407 static msurface_t surface;
12408 const msurface_t *surfacelist = &surface;
12410 // fake enough texture and surface state to render this geometry
12412 surface.texture = texture;
12413 surface.num_triangles = numtriangles;
12414 surface.num_firsttriangle = firsttriangle;
12415 surface.num_vertices = numvertices;
12416 surface.num_firstvertex = firstvertex;
12419 rsurface.texture = R_GetCurrentTexture(surface.texture);
12420 rsurface.uselightmaptexture = false;
12421 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);