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_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
95 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
96 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"};
97 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"};
98 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
100 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
101 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
102 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"};
104 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
105 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
106 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
107 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
108 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
109 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
110 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
111 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
113 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)"};
114 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"};
116 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
117 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
118 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
119 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
120 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
122 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
123 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
124 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
126 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)"};
127 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
128 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
129 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
130 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
131 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)"};
132 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)"};
133 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)"};
134 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)"};
136 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)"};
137 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
138 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"};
139 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
140 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
142 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
143 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
144 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
145 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
147 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
148 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
149 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
150 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
151 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
152 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
153 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
155 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
156 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
157 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
158 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)"};
160 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"};
162 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"};
164 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
166 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
167 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
168 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"};
169 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
170 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
171 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
172 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
173 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)"};
175 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
177 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)"};
179 extern cvar_t v_glslgamma;
181 extern qboolean v_flipped_state;
183 static struct r_bloomstate_s
188 int bloomwidth, bloomheight;
190 int screentexturewidth, screentextureheight;
191 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
193 int bloomtexturewidth, bloomtextureheight;
194 rtexture_t *texture_bloom;
196 // arrays for rendering the screen passes
197 float screentexcoord2f[8];
198 float bloomtexcoord2f[8];
199 float offsettexcoord2f[8];
201 r_viewport_t viewport;
205 r_waterstate_t r_waterstate;
207 /// shadow volume bsp struct with automatically growing nodes buffer
210 rtexture_t *r_texture_blanknormalmap;
211 rtexture_t *r_texture_white;
212 rtexture_t *r_texture_grey128;
213 rtexture_t *r_texture_black;
214 rtexture_t *r_texture_notexture;
215 rtexture_t *r_texture_whitecube;
216 rtexture_t *r_texture_normalizationcube;
217 rtexture_t *r_texture_fogattenuation;
218 rtexture_t *r_texture_gammaramps;
219 unsigned int r_texture_gammaramps_serial;
220 //rtexture_t *r_texture_fogintensity;
221 rtexture_t *r_texture_reflectcube;
223 // TODO: hash lookups?
224 typedef struct cubemapinfo_s
231 int r_texture_numcubemaps;
232 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
234 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
235 unsigned int r_numqueries;
236 unsigned int r_maxqueries;
238 typedef struct r_qwskincache_s
240 char name[MAX_QPATH];
241 skinframe_t *skinframe;
245 static r_qwskincache_t *r_qwskincache;
246 static int r_qwskincache_size;
248 /// vertex coordinates for a quad that covers the screen exactly
249 const float r_screenvertex3f[12] =
257 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
260 for (i = 0;i < verts;i++)
271 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
274 for (i = 0;i < verts;i++)
284 // FIXME: move this to client?
287 if (gamemode == GAME_NEHAHRA)
289 Cvar_Set("gl_fogenable", "0");
290 Cvar_Set("gl_fogdensity", "0.2");
291 Cvar_Set("gl_fogred", "0.3");
292 Cvar_Set("gl_foggreen", "0.3");
293 Cvar_Set("gl_fogblue", "0.3");
295 r_refdef.fog_density = 0;
296 r_refdef.fog_red = 0;
297 r_refdef.fog_green = 0;
298 r_refdef.fog_blue = 0;
299 r_refdef.fog_alpha = 1;
300 r_refdef.fog_start = 0;
301 r_refdef.fog_end = 16384;
302 r_refdef.fog_height = 1<<30;
303 r_refdef.fog_fadedepth = 128;
306 static void R_BuildBlankTextures(void)
308 unsigned char data[4];
309 data[2] = 128; // normal X
310 data[1] = 128; // normal Y
311 data[0] = 255; // normal Z
312 data[3] = 128; // height
313 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
318 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
323 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
328 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
331 static void R_BuildNoTexture(void)
334 unsigned char pix[16][16][4];
335 // this makes a light grey/dark grey checkerboard texture
336 for (y = 0;y < 16;y++)
338 for (x = 0;x < 16;x++)
340 if ((y < 8) ^ (x < 8))
356 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
359 static void R_BuildWhiteCube(void)
361 unsigned char data[6*1*1*4];
362 memset(data, 255, sizeof(data));
363 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
366 static void R_BuildNormalizationCube(void)
370 vec_t s, t, intensity;
373 data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
374 for (side = 0;side < 6;side++)
376 for (y = 0;y < NORMSIZE;y++)
378 for (x = 0;x < NORMSIZE;x++)
380 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
381 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
416 intensity = 127.0f / sqrt(DotProduct(v, v));
417 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
418 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
419 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
420 data[((side*64+y)*64+x)*4+3] = 255;
424 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
428 static void R_BuildFogTexture(void)
432 unsigned char data1[FOGWIDTH][4];
433 //unsigned char data2[FOGWIDTH][4];
436 r_refdef.fogmasktable_start = r_refdef.fog_start;
437 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
438 r_refdef.fogmasktable_range = r_refdef.fogrange;
439 r_refdef.fogmasktable_density = r_refdef.fog_density;
441 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
442 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
444 d = (x * r - r_refdef.fogmasktable_start);
445 if(developer_extra.integer)
446 Con_DPrintf("%f ", d);
448 if (r_fog_exp2.integer)
449 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
451 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
452 if(developer_extra.integer)
453 Con_DPrintf(" : %f ", alpha);
454 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
455 if(developer_extra.integer)
456 Con_DPrintf(" = %f\n", alpha);
457 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
460 for (x = 0;x < FOGWIDTH;x++)
462 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
467 //data2[x][0] = 255 - b;
468 //data2[x][1] = 255 - b;
469 //data2[x][2] = 255 - b;
472 if (r_texture_fogattenuation)
474 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
475 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
479 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);
480 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
484 //=======================================================================================================================================================
486 static const char *builtinshaderstring =
487 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
488 "// written by Forest 'LordHavoc' Hale\n"
489 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
491 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
494 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
495 "#define USELIGHTMAP\n"
497 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
498 "#define USEEYEVECTOR\n"
501 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
502 "# extension GL_ARB_texture_rectangle : enable\n"
505 "#ifdef USESHADOWMAP2D\n"
506 "# ifdef GL_EXT_gpu_shader4\n"
507 "# extension GL_EXT_gpu_shader4 : enable\n"
509 "# ifdef GL_ARB_texture_gather\n"
510 "# extension GL_ARB_texture_gather : enable\n"
512 "# ifdef GL_AMD_texture_texture4\n"
513 "# extension GL_AMD_texture_texture4 : enable\n"
518 "#ifdef USESHADOWMAPCUBE\n"
519 "# extension GL_EXT_gpu_shader4 : enable\n"
522 "//#ifdef USESHADOWSAMPLER\n"
523 "//# extension GL_ARB_shadow : enable\n"
526 "//#ifdef __GLSL_CG_DATA_TYPES\n"
527 "//# define myhalf half\n"
528 "//# define myhalf2 half2\n"
529 "//# define myhalf3 half3\n"
530 "//# define myhalf4 half4\n"
532 "# define myhalf float\n"
533 "# define myhalf2 vec2\n"
534 "# define myhalf3 vec3\n"
535 "# define myhalf4 vec4\n"
538 "#ifdef VERTEX_SHADER\n"
539 "uniform mat4 ModelViewProjectionMatrix;\n"
542 "#ifdef MODE_DEPTH_OR_SHADOW\n"
543 "#ifdef VERTEX_SHADER\n"
546 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
549 "#else // !MODE_DEPTH_ORSHADOW\n"
554 "#ifdef MODE_SHOWDEPTH\n"
555 "#ifdef VERTEX_SHADER\n"
558 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
559 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
563 "#ifdef FRAGMENT_SHADER\n"
566 " gl_FragColor = gl_Color;\n"
569 "#else // !MODE_SHOWDEPTH\n"
574 "#ifdef MODE_POSTPROCESS\n"
575 "varying vec2 TexCoord1;\n"
576 "varying vec2 TexCoord2;\n"
578 "#ifdef VERTEX_SHADER\n"
581 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
582 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
584 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
589 "#ifdef FRAGMENT_SHADER\n"
590 "uniform sampler2D Texture_First;\n"
592 "uniform sampler2D Texture_Second;\n"
594 "#ifdef USEGAMMARAMPS\n"
595 "uniform sampler2D Texture_GammaRamps;\n"
597 "#ifdef USESATURATION\n"
598 "uniform float Saturation;\n"
600 "#ifdef USEVIEWTINT\n"
601 "uniform vec4 ViewTintColor;\n"
603 "//uncomment these if you want to use them:\n"
604 "uniform vec4 UserVec1;\n"
605 "// uniform vec4 UserVec2;\n"
606 "// uniform vec4 UserVec3;\n"
607 "// uniform vec4 UserVec4;\n"
608 "// uniform float ClientTime;\n"
609 "uniform vec2 PixelSize;\n"
612 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
614 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
616 "#ifdef USEVIEWTINT\n"
617 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
620 "#ifdef USEPOSTPROCESSING\n"
621 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
622 "// 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"
623 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
624 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
625 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
626 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
627 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
628 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
631 "#ifdef USESATURATION\n"
632 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
633 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
634 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
635 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
638 "#ifdef USEGAMMARAMPS\n"
639 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
640 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
641 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
645 "#else // !MODE_POSTPROCESS\n"
650 "#ifdef MODE_GENERIC\n"
651 "#ifdef USEDIFFUSE\n"
652 "varying vec2 TexCoord1;\n"
654 "#ifdef USESPECULAR\n"
655 "varying vec2 TexCoord2;\n"
657 "#ifdef VERTEX_SHADER\n"
660 " gl_FrontColor = gl_Color;\n"
661 "#ifdef USEDIFFUSE\n"
662 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
664 "#ifdef USESPECULAR\n"
665 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
667 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
671 "#ifdef FRAGMENT_SHADER\n"
672 "#ifdef USEDIFFUSE\n"
673 "uniform sampler2D Texture_First;\n"
675 "#ifdef USESPECULAR\n"
676 "uniform sampler2D Texture_Second;\n"
681 " gl_FragColor = gl_Color;\n"
682 "#ifdef USEDIFFUSE\n"
683 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
686 "#ifdef USESPECULAR\n"
687 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
688 "# ifdef USECOLORMAPPING\n"
689 " gl_FragColor *= tex2;\n"
692 " gl_FragColor += tex2;\n"
694 "# ifdef USEVERTEXTEXTUREBLEND\n"
695 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
700 "#else // !MODE_GENERIC\n"
705 "#ifdef MODE_BLOOMBLUR\n"
706 "varying TexCoord;\n"
707 "#ifdef VERTEX_SHADER\n"
710 " gl_FrontColor = gl_Color;\n"
711 " TexCoord = gl_MultiTexCoord0.xy;\n"
712 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
716 "#ifdef FRAGMENT_SHADER\n"
717 "uniform sampler2D Texture_First;\n"
718 "uniform vec4 BloomBlur_Parameters;\n"
723 " vec2 tc = TexCoord;\n"
724 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
725 " tc += BloomBlur_Parameters.xy;\n"
726 " for (i = 1;i < SAMPLES;i++)\n"
728 " color += texture2D(Texture_First, tc).rgb;\n"
729 " tc += BloomBlur_Parameters.xy;\n"
731 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
734 "#else // !MODE_BLOOMBLUR\n"
735 "#ifdef MODE_REFRACTION\n"
736 "varying vec2 TexCoord;\n"
737 "varying vec4 ModelViewProjectionPosition;\n"
738 "uniform mat4 TexMatrix;\n"
739 "#ifdef VERTEX_SHADER\n"
743 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
744 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
745 " ModelViewProjectionPosition = gl_Position;\n"
749 "#ifdef FRAGMENT_SHADER\n"
750 "uniform sampler2D Texture_Normal;\n"
751 "uniform sampler2D Texture_Refraction;\n"
752 "uniform sampler2D Texture_Reflection;\n"
754 "uniform vec4 DistortScaleRefractReflect;\n"
755 "uniform vec4 ScreenScaleRefractReflect;\n"
756 "uniform vec4 ScreenCenterRefractReflect;\n"
757 "uniform vec4 RefractColor;\n"
758 "uniform vec4 ReflectColor;\n"
759 "uniform float ReflectFactor;\n"
760 "uniform float ReflectOffset;\n"
764 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
765 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
766 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
767 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
768 " // FIXME temporary hack to detect the case that the reflection\n"
769 " // gets blackened at edges due to leaving the area that contains actual\n"
771 " // Remove this 'ack once we have a better way to stop this thing from\n"
773 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
774 " 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 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
778 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
781 "#else // !MODE_REFRACTION\n"
786 "#ifdef MODE_WATER\n"
787 "varying vec2 TexCoord;\n"
788 "varying vec3 EyeVector;\n"
789 "varying vec4 ModelViewProjectionPosition;\n"
790 "#ifdef VERTEX_SHADER\n"
791 "uniform vec3 EyePosition;\n"
792 "uniform mat4 TexMatrix;\n"
796 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
797 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
798 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
799 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
800 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
801 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
802 " ModelViewProjectionPosition = gl_Position;\n"
806 "#ifdef FRAGMENT_SHADER\n"
807 "uniform sampler2D Texture_Normal;\n"
808 "uniform sampler2D Texture_Refraction;\n"
809 "uniform sampler2D Texture_Reflection;\n"
811 "uniform vec4 DistortScaleRefractReflect;\n"
812 "uniform vec4 ScreenScaleRefractReflect;\n"
813 "uniform vec4 ScreenCenterRefractReflect;\n"
814 "uniform vec4 RefractColor;\n"
815 "uniform vec4 ReflectColor;\n"
816 "uniform float ReflectFactor;\n"
817 "uniform float ReflectOffset;\n"
821 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
822 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
823 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
824 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
825 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
826 " // FIXME temporary hack to detect the case that the reflection\n"
827 " // gets blackened at edges due to leaving the area that contains actual\n"
829 " // Remove this 'ack once we have a better way to stop this thing from\n"
831 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
832 " 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 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
836 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\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 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
841 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
842 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
845 "#else // !MODE_WATER\n"
850 "// common definitions between vertex shader and fragment shader:\n"
852 "varying vec2 TexCoord;\n"
853 "#ifdef USEVERTEXTEXTUREBLEND\n"
854 "varying vec2 TexCoord2;\n"
856 "#ifdef USELIGHTMAP\n"
857 "varying vec2 TexCoordLightmap;\n"
860 "#ifdef MODE_LIGHTSOURCE\n"
861 "varying vec3 CubeVector;\n"
864 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
865 "varying vec3 LightVector;\n"
868 "#ifdef USEEYEVECTOR\n"
869 "varying vec3 EyeVector;\n"
872 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
875 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
876 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
877 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
878 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
881 "#ifdef USEREFLECTION\n"
882 "varying vec4 ModelViewProjectionPosition;\n"
884 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
885 "uniform vec3 LightPosition;\n"
886 "varying vec4 ModelViewPosition;\n"
889 "#ifdef MODE_LIGHTSOURCE\n"
890 "uniform vec3 LightPosition;\n"
892 "uniform vec3 EyePosition;\n"
893 "#ifdef MODE_LIGHTDIRECTION\n"
894 "uniform vec3 LightDir;\n"
896 "uniform vec4 FogPlane;\n"
898 "#ifdef USESHADOWMAPORTHO\n"
899 "varying vec3 ShadowMapTC;\n"
906 "// 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"
908 "// fragment shader specific:\n"
909 "#ifdef FRAGMENT_SHADER\n"
911 "uniform sampler2D Texture_Normal;\n"
912 "uniform sampler2D Texture_Color;\n"
913 "uniform sampler2D Texture_Gloss;\n"
915 "uniform sampler2D Texture_Glow;\n"
917 "#ifdef USEVERTEXTEXTUREBLEND\n"
918 "uniform sampler2D Texture_SecondaryNormal;\n"
919 "uniform sampler2D Texture_SecondaryColor;\n"
920 "uniform sampler2D Texture_SecondaryGloss;\n"
922 "uniform sampler2D Texture_SecondaryGlow;\n"
925 "#ifdef USECOLORMAPPING\n"
926 "uniform sampler2D Texture_Pants;\n"
927 "uniform sampler2D Texture_Shirt;\n"
930 "uniform sampler2D Texture_FogMask;\n"
932 "#ifdef USELIGHTMAP\n"
933 "uniform sampler2D Texture_Lightmap;\n"
935 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
936 "uniform sampler2D Texture_Deluxemap;\n"
938 "#ifdef USEREFLECTION\n"
939 "uniform sampler2D Texture_Reflection;\n"
942 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
943 "uniform sampler2D Texture_ScreenDepth;\n"
944 "uniform sampler2D Texture_ScreenNormalMap;\n"
946 "#ifdef USEDEFERREDLIGHTMAP\n"
947 "uniform sampler2D Texture_ScreenDiffuse;\n"
948 "uniform sampler2D Texture_ScreenSpecular;\n"
951 "uniform myhalf3 Color_Pants;\n"
952 "uniform myhalf3 Color_Shirt;\n"
953 "uniform myhalf3 FogColor;\n"
956 "uniform float FogRangeRecip;\n"
957 "uniform float FogPlaneViewDist;\n"
958 "uniform float FogHeightFade;\n"
959 "float FogVertex(void)\n"
961 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
962 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
964 "#ifdef USEFOGOUTSIDE\n"
965 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
967 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
969 " return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
973 "#ifdef USEOFFSETMAPPING\n"
974 "uniform float OffsetMapping_Scale;\n"
975 "vec2 OffsetMapping(vec2 TexCoord)\n"
977 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
978 " // 14 sample relief mapping: linear search and then binary search\n"
979 " // this basically steps forward a small amount repeatedly until it finds\n"
980 " // itself inside solid, then jitters forward and back using decreasing\n"
981 " // amounts to find the impact\n"
982 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
983 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
984 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
985 " vec3 RT = vec3(TexCoord, 1);\n"
986 " OffsetVector *= 0.1;\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);\n"
994 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
995 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
996 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
997 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
998 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
999 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1000 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1003 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1004 " // this basically moves forward the full distance, and then backs up based\n"
1005 " // on height of samples\n"
1006 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1007 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1008 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1009 " TexCoord += OffsetVector;\n"
1010 " OffsetVector *= 0.333;\n"
1011 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1012 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1013 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1014 " return TexCoord;\n"
1017 "#endif // USEOFFSETMAPPING\n"
1019 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1020 "uniform sampler2D Texture_Attenuation;\n"
1021 "uniform samplerCube Texture_Cube;\n"
1024 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1026 "#ifdef USESHADOWMAPRECT\n"
1027 "# ifdef USESHADOWSAMPLER\n"
1028 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1030 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1034 "#ifdef USESHADOWMAP2D\n"
1035 "# ifdef USESHADOWSAMPLER\n"
1036 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1038 "uniform sampler2D Texture_ShadowMap2D;\n"
1042 "#ifdef USESHADOWMAPVSDCT\n"
1043 "uniform samplerCube Texture_CubeProjection;\n"
1046 "#ifdef USESHADOWMAPCUBE\n"
1047 "# ifdef USESHADOWSAMPLER\n"
1048 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1050 "uniform samplerCube Texture_ShadowMapCube;\n"
1054 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1055 "uniform vec2 ShadowMap_TextureScale;\n"
1056 "uniform vec4 ShadowMap_Parameters;\n"
1059 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1060 "# ifdef USESHADOWMAPORTHO\n"
1061 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1063 "# ifdef USESHADOWMAPVSDCT\n"
1064 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1066 " vec3 adir = abs(dir);\n"
1067 " float ma = max(max(adir.x, adir.y), adir.z);\n"
1068 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1069 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1070 " stc += vec3(proj.zw * ShadowMap_Parameters.y, ShadowMap_Parameters.z);\n"
1074 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1076 " vec3 adir = abs(dir);\n"
1077 " float ma = adir.z;\n"
1078 " vec4 proj = vec4(dir, 2.5);\n"
1079 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1080 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1081 " vec3 stc = vec3(proj.xy * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1082 " stc += vec3(vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.y, ShadowMap_Parameters.z);\n"
1087 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1089 "#ifdef USESHADOWMAPCUBE\n"
1090 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1092 " vec3 adir = abs(dir);\n"
1093 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1097 "# ifdef USESHADOWMAPRECT\n"
1098 "float ShadowMapCompare(vec3 dir)\n"
1100 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1102 "# ifdef USESHADOWSAMPLER\n"
1104 "# ifdef USESHADOWMAPPCF\n"
1105 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1106 " 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"
1108 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1113 "# ifdef USESHADOWMAPPCF\n"
1114 "# if USESHADOWMAPPCF > 1\n"
1115 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1116 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1117 " 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"
1118 " 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"
1119 " 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"
1120 " 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"
1121 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1122 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1124 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1125 " vec2 offset = fract(shadowmaptc.xy);\n"
1126 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1127 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1128 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1129 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1130 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1133 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1137 "# ifdef USESHADOWMAPORTHO\n"
1138 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1145 "# ifdef USESHADOWMAP2D\n"
1146 "float ShadowMapCompare(vec3 dir)\n"
1148 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1151 "# ifdef USESHADOWSAMPLER\n"
1152 "# ifdef USESHADOWMAPPCF\n"
1153 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1154 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1155 " 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"
1157 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1160 "# ifdef USESHADOWMAPPCF\n"
1161 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1162 "# ifdef GL_ARB_texture_gather\n"
1163 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1165 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1167 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1168 " center *= ShadowMap_TextureScale;\n"
1169 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1170 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1171 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1172 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1173 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1174 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1175 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1177 "# ifdef GL_EXT_gpu_shader4\n"
1178 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1180 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1182 "# if USESHADOWMAPPCF > 1\n"
1183 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1184 " center *= ShadowMap_TextureScale;\n"
1185 " 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"
1186 " 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"
1187 " 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"
1188 " 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"
1189 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1190 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1192 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1193 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1194 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1195 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1196 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1197 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1201 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1204 "# ifdef USESHADOWMAPORTHO\n"
1205 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1212 "# ifdef USESHADOWMAPCUBE\n"
1213 "float ShadowMapCompare(vec3 dir)\n"
1215 " // apply depth texture cubemap as light filter\n"
1216 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1218 "# ifdef USESHADOWSAMPLER\n"
1219 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1221 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1226 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1227 "#endif // FRAGMENT_SHADER\n"
1232 "#ifdef MODE_DEFERREDGEOMETRY\n"
1233 "#ifdef VERTEX_SHADER\n"
1234 "uniform mat4 TexMatrix;\n"
1235 "#ifdef USEVERTEXTEXTUREBLEND\n"
1236 "uniform mat4 BackgroundTexMatrix;\n"
1238 "uniform mat4 ModelViewMatrix;\n"
1241 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1242 "#ifdef USEVERTEXTEXTUREBLEND\n"
1243 " gl_FrontColor = gl_Color;\n"
1244 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1247 " // transform unnormalized eye direction into tangent space\n"
1248 "#ifdef USEOFFSETMAPPING\n"
1249 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1250 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1251 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1252 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1255 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1256 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1257 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1258 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1260 "#endif // VERTEX_SHADER\n"
1262 "#ifdef FRAGMENT_SHADER\n"
1265 "#ifdef USEOFFSETMAPPING\n"
1266 " // apply offsetmapping\n"
1267 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1268 "#define TexCoord TexCoordOffset\n"
1271 "#ifdef USEALPHAKILL\n"
1272 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1276 "#ifdef USEVERTEXTEXTUREBLEND\n"
1277 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1278 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1279 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1280 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1283 "#ifdef USEVERTEXTEXTUREBLEND\n"
1284 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1285 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1287 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1288 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1291 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1293 "#endif // FRAGMENT_SHADER\n"
1294 "#else // !MODE_DEFERREDGEOMETRY\n"
1299 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1300 "#ifdef VERTEX_SHADER\n"
1301 "uniform mat4 ModelViewMatrix;\n"
1304 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1305 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1307 "#endif // VERTEX_SHADER\n"
1309 "#ifdef FRAGMENT_SHADER\n"
1310 "uniform mat4 ViewToLight;\n"
1311 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1312 "uniform vec2 ScreenToDepth;\n"
1313 "uniform myhalf3 DeferredColor_Ambient;\n"
1314 "uniform myhalf3 DeferredColor_Diffuse;\n"
1315 "#ifdef USESPECULAR\n"
1316 "uniform myhalf3 DeferredColor_Specular;\n"
1317 "uniform myhalf SpecularPower;\n"
1319 "uniform myhalf2 PixelToScreenTexCoord;\n"
1322 " // calculate viewspace pixel position\n"
1323 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1325 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1326 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1327 " // decode viewspace pixel normal\n"
1328 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1329 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1330 " // surfacenormal = pixel normal in viewspace\n"
1331 " // LightVector = pixel to light in viewspace\n"
1332 " // CubeVector = position in lightspace\n"
1333 " // eyevector = pixel to view in viewspace\n"
1334 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1335 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1336 "#ifdef USEDIFFUSE\n"
1337 " // calculate diffuse shading\n"
1338 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1339 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1341 "#ifdef USESPECULAR\n"
1342 " // calculate directional shading\n"
1343 " vec3 eyevector = position * -1.0;\n"
1344 "# ifdef USEEXACTSPECULARMATH\n"
1345 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1347 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1348 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1352 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1353 " fade *= ShadowMapCompare(CubeVector);\n"
1356 "#ifdef USEDIFFUSE\n"
1357 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1359 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1361 "#ifdef USESPECULAR\n"
1362 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1364 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1367 "# ifdef USECUBEFILTER\n"
1368 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1369 " gl_FragData[0].rgb *= cubecolor;\n"
1370 " gl_FragData[1].rgb *= cubecolor;\n"
1373 "#endif // FRAGMENT_SHADER\n"
1374 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1379 "#ifdef VERTEX_SHADER\n"
1380 "uniform mat4 TexMatrix;\n"
1381 "#ifdef USEVERTEXTEXTUREBLEND\n"
1382 "uniform mat4 BackgroundTexMatrix;\n"
1384 "#ifdef MODE_LIGHTSOURCE\n"
1385 "uniform mat4 ModelToLight;\n"
1387 "#ifdef USESHADOWMAPORTHO\n"
1388 "uniform mat4 ShadowMapMatrix;\n"
1392 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1393 " gl_FrontColor = gl_Color;\n"
1395 " // copy the surface texcoord\n"
1396 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1397 "#ifdef USEVERTEXTEXTUREBLEND\n"
1398 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1400 "#ifdef USELIGHTMAP\n"
1401 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1404 "#ifdef MODE_LIGHTSOURCE\n"
1405 " // transform vertex position into light attenuation/cubemap space\n"
1406 " // (-1 to +1 across the light box)\n"
1407 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1409 "# ifdef USEDIFFUSE\n"
1410 " // transform unnormalized light direction into tangent space\n"
1411 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1412 " // normalize it per pixel)\n"
1413 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1414 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1415 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1416 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1420 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1421 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1422 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1423 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1426 " // transform unnormalized eye direction into tangent space\n"
1427 "#ifdef USEEYEVECTOR\n"
1428 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1429 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1430 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1431 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1435 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1436 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1439 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1440 " VectorS = gl_MultiTexCoord1.xyz;\n"
1441 " VectorT = gl_MultiTexCoord2.xyz;\n"
1442 " VectorR = gl_MultiTexCoord3.xyz;\n"
1445 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1446 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1448 "#ifdef USESHADOWMAPORTHO\n"
1449 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1452 "#ifdef USEREFLECTION\n"
1453 " ModelViewProjectionPosition = gl_Position;\n"
1456 "#endif // VERTEX_SHADER\n"
1461 "#ifdef FRAGMENT_SHADER\n"
1462 "#ifdef USEDEFERREDLIGHTMAP\n"
1463 "uniform myhalf2 PixelToScreenTexCoord;\n"
1464 "uniform myhalf3 DeferredMod_Diffuse;\n"
1465 "uniform myhalf3 DeferredMod_Specular;\n"
1467 "uniform myhalf3 Color_Ambient;\n"
1468 "uniform myhalf3 Color_Diffuse;\n"
1469 "uniform myhalf3 Color_Specular;\n"
1470 "uniform myhalf SpecularPower;\n"
1472 "uniform myhalf3 Color_Glow;\n"
1474 "uniform myhalf Alpha;\n"
1475 "#ifdef USEREFLECTION\n"
1476 "uniform vec4 DistortScaleRefractReflect;\n"
1477 "uniform vec4 ScreenScaleRefractReflect;\n"
1478 "uniform vec4 ScreenCenterRefractReflect;\n"
1479 "uniform myhalf4 ReflectColor;\n"
1481 "#ifdef USEREFLECTCUBE\n"
1482 "uniform mat4 ModelToReflectCube;\n"
1483 "uniform sampler2D Texture_ReflectMask;\n"
1484 "uniform samplerCube Texture_ReflectCube;\n"
1486 "#ifdef MODE_LIGHTDIRECTION\n"
1487 "uniform myhalf3 LightColor;\n"
1489 "#ifdef MODE_LIGHTSOURCE\n"
1490 "uniform myhalf3 LightColor;\n"
1494 "#ifdef USEOFFSETMAPPING\n"
1495 " // apply offsetmapping\n"
1496 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1497 "#define TexCoord TexCoordOffset\n"
1500 " // combine the diffuse textures (base, pants, shirt)\n"
1501 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1502 "#ifdef USEALPHAKILL\n"
1503 " if (color.a < 0.5)\n"
1506 " color.a *= Alpha;\n"
1507 "#ifdef USECOLORMAPPING\n"
1508 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1510 "#ifdef USEVERTEXTEXTUREBLEND\n"
1511 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1512 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1513 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1514 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1516 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1519 " // get the surface normal\n"
1520 "#ifdef USEVERTEXTEXTUREBLEND\n"
1521 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1523 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1526 " // get the material colors\n"
1527 " myhalf3 diffusetex = color.rgb;\n"
1528 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1529 "# ifdef USEVERTEXTEXTUREBLEND\n"
1530 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1532 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1536 "#ifdef USEREFLECTCUBE\n"
1537 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1538 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1539 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1540 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1546 "#ifdef MODE_LIGHTSOURCE\n"
1547 " // light source\n"
1548 "#ifdef USEDIFFUSE\n"
1549 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1550 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1551 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1552 "#ifdef USESPECULAR\n"
1553 "#ifdef USEEXACTSPECULARMATH\n"
1554 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1556 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1557 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1559 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1562 " color.rgb = diffusetex * Color_Ambient;\n"
1564 " color.rgb *= LightColor;\n"
1565 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1566 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1567 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1569 "# ifdef USECUBEFILTER\n"
1570 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1572 "#endif // MODE_LIGHTSOURCE\n"
1577 "#ifdef MODE_LIGHTDIRECTION\n"
1579 "#ifdef USEDIFFUSE\n"
1580 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1582 "#define lightcolor LightColor\n"
1583 "#endif // MODE_LIGHTDIRECTION\n"
1584 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1586 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1587 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1588 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1589 " // convert modelspace light vector to tangentspace\n"
1590 " myhalf3 lightnormal;\n"
1591 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1592 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1593 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1594 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1595 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1596 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1597 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1598 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1599 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1600 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1601 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1602 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1603 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1604 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1605 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1607 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1608 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1609 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1615 "#ifdef MODE_LIGHTMAP\n"
1616 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1617 "#endif // MODE_LIGHTMAP\n"
1618 "#ifdef MODE_VERTEXCOLOR\n"
1619 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1620 "#endif // MODE_VERTEXCOLOR\n"
1621 "#ifdef MODE_FLATCOLOR\n"
1622 " color.rgb = diffusetex * Color_Ambient;\n"
1623 "#endif // MODE_FLATCOLOR\n"
1629 "# ifdef USEDIFFUSE\n"
1630 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1631 "# ifdef USESPECULAR\n"
1632 "# ifdef USEEXACTSPECULARMATH\n"
1633 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1635 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1636 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1638 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1640 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1643 " color.rgb = diffusetex * Color_Ambient;\n"
1647 "#ifdef USESHADOWMAPORTHO\n"
1648 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1651 "#ifdef USEDEFERREDLIGHTMAP\n"
1652 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1653 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1654 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1658 "#ifdef USEVERTEXTEXTUREBLEND\n"
1659 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1661 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1666 "#ifdef MODE_LIGHTSOURCE\n"
1667 " color.rgb *= myhalf(FogVertex());\n"
1669 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1673 " // 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"
1674 "#ifdef USEREFLECTION\n"
1675 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1676 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1677 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1678 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1679 " // FIXME temporary hack to detect the case that the reflection\n"
1680 " // gets blackened at edges due to leaving the area that contains actual\n"
1682 " // Remove this 'ack once we have a better way to stop this thing from\n"
1684 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1685 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1686 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1687 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1688 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1689 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1692 " gl_FragColor = vec4(color);\n"
1694 "#endif // FRAGMENT_SHADER\n"
1696 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1697 "#endif // !MODE_DEFERREDGEOMETRY\n"
1698 "#endif // !MODE_WATER\n"
1699 "#endif // !MODE_REFRACTION\n"
1700 "#endif // !MODE_BLOOMBLUR\n"
1701 "#endif // !MODE_GENERIC\n"
1702 "#endif // !MODE_POSTPROCESS\n"
1703 "#endif // !MODE_SHOWDEPTH\n"
1704 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1708 =========================================================================================================================================================
1712 =========================================================================================================================================================
1716 =========================================================================================================================================================
1720 =========================================================================================================================================================
1724 =========================================================================================================================================================
1728 =========================================================================================================================================================
1732 =========================================================================================================================================================
1735 const char *builtincgshaderstring =
1736 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1737 "// written by Forest 'LordHavoc' Hale\n"
1738 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1740 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1743 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1744 "#define USELIGHTMAP\n"
1746 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1747 "#define USEEYEVECTOR\n"
1750 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1751 "#ifdef VERTEX_SHADER\n"
1754 "float4 gl_Vertex : POSITION,\n"
1755 "uniform float4x4 ModelViewProjectionMatrix,\n"
1756 "out float4 gl_Position : POSITION\n"
1759 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1762 "#else // !MODE_DEPTH_ORSHADOW\n"
1767 "#ifdef MODE_SHOWDEPTH\n"
1768 "#ifdef VERTEX_SHADER\n"
1771 "float4 gl_Vertex : POSITION,\n"
1772 "uniform float4x4 ModelViewProjectionMatrix,\n"
1773 "out float4 gl_Position : POSITION,\n"
1774 "out float4 gl_FrontColor : COLOR0\n"
1777 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1778 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1782 "#ifdef FRAGMENT_SHADER\n"
1785 "float4 gl_FrontColor : COLOR0,\n"
1786 "out float4 gl_FragColor : COLOR\n"
1789 " gl_FragColor = gl_FrontColor;\n"
1792 "#else // !MODE_SHOWDEPTH\n"
1797 "#ifdef MODE_POSTPROCESS\n"
1799 "#ifdef VERTEX_SHADER\n"
1802 "float4 gl_Vertex : POSITION,\n"
1803 "uniform float4x4 ModelViewProjectionMatrix,\n"
1804 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1805 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1806 "out float4 gl_Position : POSITION,\n"
1807 "out float2 TexCoord1 : TEXCOORD0,\n"
1808 "out float2 TexCoord2 : TEXCOORD1\n"
1811 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1812 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1814 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1819 "#ifdef FRAGMENT_SHADER\n"
1822 "float2 TexCoord1 : TEXCOORD0,\n"
1823 "float2 TexCoord2 : TEXCOORD1,\n"
1824 "uniform sampler2D Texture_First,\n"
1826 "uniform sampler2D Texture_Second,\n"
1828 "#ifdef USEGAMMARAMPS\n"
1829 "uniform sampler2D Texture_GammaRamps,\n"
1831 "#ifdef USESATURATION\n"
1832 "uniform float Saturation,\n"
1834 "#ifdef USEVIEWTINT\n"
1835 "uniform float4 ViewTintColor,\n"
1837 "uniform float4 UserVec1,\n"
1838 "uniform float4 UserVec2,\n"
1839 "uniform float4 UserVec3,\n"
1840 "uniform float4 UserVec4,\n"
1841 "uniform float ClientTime,\n"
1842 "uniform float2 PixelSize,\n"
1843 "out float4 gl_FragColor : COLOR\n"
1846 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1848 " gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1850 "#ifdef USEVIEWTINT\n"
1851 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1854 "#ifdef USEPOSTPROCESSING\n"
1855 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1856 "// 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"
1857 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1858 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1859 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1860 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1861 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1862 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1865 "#ifdef USESATURATION\n"
1866 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1867 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1868 " //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1869 " gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1872 "#ifdef USEGAMMARAMPS\n"
1873 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1874 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1875 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1879 "#else // !MODE_POSTPROCESS\n"
1884 "#ifdef MODE_GENERIC\n"
1885 "#ifdef VERTEX_SHADER\n"
1888 "float4 gl_Vertex : POSITION,\n"
1889 "uniform float4x4 ModelViewProjectionMatrix,\n"
1890 "float4 gl_Color : COLOR0,\n"
1891 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1892 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1893 "out float4 gl_Position : POSITION,\n"
1894 "out float4 gl_FrontColor : COLOR,\n"
1895 "out float2 TexCoord1 : TEXCOORD0,\n"
1896 "out float2 TexCoord2 : TEXCOORD1\n"
1899 " gl_FrontColor = gl_Color;\n"
1900 "#ifdef USEDIFFUSE\n"
1901 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1903 "#ifdef USESPECULAR\n"
1904 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1906 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1910 "#ifdef FRAGMENT_SHADER\n"
1914 "float4 gl_FrontColor : COLOR,\n"
1915 "float2 TexCoord1 : TEXCOORD0,\n"
1916 "float2 TexCoord2 : TEXCOORD1,\n"
1917 "#ifdef USEDIFFUSE\n"
1918 "uniform sampler2D Texture_First,\n"
1920 "#ifdef USESPECULAR\n"
1921 "uniform sampler2D Texture_Second,\n"
1923 "out float4 gl_FragColor : COLOR\n"
1926 " gl_FragColor = gl_FrontColor;\n"
1927 "#ifdef USEDIFFUSE\n"
1928 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1931 "#ifdef USESPECULAR\n"
1932 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1933 "# ifdef USECOLORMAPPING\n"
1934 " gl_FragColor *= tex2;\n"
1937 " gl_FragColor += tex2;\n"
1939 "# ifdef USEVERTEXTEXTUREBLEND\n"
1940 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1945 "#else // !MODE_GENERIC\n"
1950 "#ifdef MODE_BLOOMBLUR\n"
1951 "#ifdef VERTEX_SHADER\n"
1954 "float4 gl_Vertex : POSITION,\n"
1955 "uniform float4x4 ModelViewProjectionMatrix,\n"
1956 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1957 "out float4 gl_Position : POSITION,\n"
1958 "out float2 TexCoord : TEXCOORD0\n"
1961 " TexCoord = gl_MultiTexCoord0.xy;\n"
1962 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1966 "#ifdef FRAGMENT_SHADER\n"
1970 "float2 TexCoord : TEXCOORD0,\n"
1971 "uniform sampler2D Texture_First,\n"
1972 "uniform float4 BloomBlur_Parameters,\n"
1973 "out float4 gl_FragColor : COLOR\n"
1977 " float2 tc = TexCoord;\n"
1978 " float3 color = tex2D(Texture_First, tc).rgb;\n"
1979 " tc += BloomBlur_Parameters.xy;\n"
1980 " for (i = 1;i < SAMPLES;i++)\n"
1982 " color += tex2D(Texture_First, tc).rgb;\n"
1983 " tc += BloomBlur_Parameters.xy;\n"
1985 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1988 "#else // !MODE_BLOOMBLUR\n"
1989 "#ifdef MODE_REFRACTION\n"
1990 "#ifdef VERTEX_SHADER\n"
1993 "float4 gl_Vertex : POSITION,\n"
1994 "uniform float4x4 ModelViewProjectionMatrix,\n"
1995 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1996 "uniform float4x4 TexMatrix,\n"
1997 "uniform float3 EyePosition,\n"
1998 "out float4 gl_Position : POSITION,\n"
1999 "out float2 TexCoord : TEXCOORD0,\n"
2000 "out float3 EyeVector : TEXCOORD1,\n"
2001 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2004 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2005 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2006 " ModelViewProjectionPosition = gl_Position;\n"
2010 "#ifdef FRAGMENT_SHADER\n"
2013 "float2 TexCoord : TEXCOORD0,\n"
2014 "float3 EyeVector : TEXCOORD1,\n"
2015 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2016 "uniform sampler2D Texture_Normal,\n"
2017 "uniform sampler2D Texture_Refraction,\n"
2018 "uniform sampler2D Texture_Reflection,\n"
2019 "uniform float4 DistortScaleRefractReflect,\n"
2020 "uniform float4 ScreenScaleRefractReflect,\n"
2021 "uniform float4 ScreenCenterRefractReflect,\n"
2022 "uniform float4 RefractColor,\n"
2023 "out float4 gl_FragColor : COLOR\n"
2026 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2027 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2028 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2029 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2030 " // FIXME temporary hack to detect the case that the reflection\n"
2031 " // gets blackened at edges due to leaving the area that contains actual\n"
2033 " // Remove this 'ack once we have a better way to stop this thing from\n"
2035 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2036 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2037 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2038 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2039 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2040 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2043 "#else // !MODE_REFRACTION\n"
2048 "#ifdef MODE_WATER\n"
2049 "#ifdef VERTEX_SHADER\n"
2053 "float4 gl_Vertex : POSITION,\n"
2054 "uniform float4x4 ModelViewProjectionMatrix,\n"
2055 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2056 "uniform float4x4 TexMatrix,\n"
2057 "uniform float3 EyePosition,\n"
2058 "out float4 gl_Position : POSITION,\n"
2059 "out float2 TexCoord : TEXCOORD0,\n"
2060 "out float3 EyeVector : TEXCOORD1,\n"
2061 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2064 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2065 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2066 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2067 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2068 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2069 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2070 " ModelViewProjectionPosition = gl_Position;\n"
2074 "#ifdef FRAGMENT_SHADER\n"
2077 "float2 TexCoord : TEXCOORD0,\n"
2078 "float3 EyeVector : TEXCOORD1,\n"
2079 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2080 "uniform sampler2D Texture_Normal,\n"
2081 "uniform sampler2D Texture_Refraction,\n"
2082 "uniform sampler2D Texture_Reflection,\n"
2083 "uniform float4 DistortScaleRefractReflect,\n"
2084 "uniform float4 ScreenScaleRefractReflect,\n"
2085 "uniform float4 ScreenCenterRefractReflect,\n"
2086 "uniform float4 RefractColor,\n"
2087 "uniform float4 ReflectColor,\n"
2088 "uniform float ReflectFactor,\n"
2089 "uniform float ReflectOffset,\n"
2090 "out float4 gl_FragColor : COLOR\n"
2093 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2094 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2095 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2096 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2097 " // FIXME temporary hack to detect the case that the reflection\n"
2098 " // gets blackened at edges due to leaving the area that contains actual\n"
2100 " // Remove this 'ack once we have a better way to stop this thing from\n"
2102 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2103 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2104 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2105 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2106 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2107 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2108 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2109 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2110 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2111 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2112 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2113 " gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2116 "#else // !MODE_WATER\n"
2121 "// 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"
2123 "// fragment shader specific:\n"
2124 "#ifdef FRAGMENT_SHADER\n"
2127 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2130 "#ifdef USEFOGOUTSIDE\n"
2131 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2133 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2135 " return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2139 "#ifdef USEOFFSETMAPPING\n"
2140 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2142 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2143 " // 14 sample relief mapping: linear search and then binary search\n"
2144 " // this basically steps forward a small amount repeatedly until it finds\n"
2145 " // itself inside solid, then jitters forward and back using decreasing\n"
2146 " // amounts to find the impact\n"
2147 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2148 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2149 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2150 " float3 RT = float3(TexCoord, 1);\n"
2151 " OffsetVector *= 0.1;\n"
2152 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2153 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2154 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
2162 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2163 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2164 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2165 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2168 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2169 " // this basically moves forward the full distance, and then backs up based\n"
2170 " // on height of samples\n"
2171 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2172 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2173 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2174 " TexCoord += OffsetVector;\n"
2175 " OffsetVector *= 0.333;\n"
2176 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2177 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2178 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2179 " return TexCoord;\n"
2182 "#endif // USEOFFSETMAPPING\n"
2184 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2185 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2186 "# ifdef USESHADOWMAPORTHO\n"
2187 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2189 "# ifdef USESHADOWMAPVSDCT\n"
2190 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2192 " float3 adir = abs(dir);\n"
2193 " float ma = max(max(adir.x, adir.y), adir.z);\n"
2194 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2195 " float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2196 " stc += float3(proj.zw * ShadowMap_Parameters.y, ShadowMap_Parameters.z);\n"
2200 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2202 " float3 adir = abs(dir);\n"
2203 " float ma = adir.z;\n"
2204 " float4 proj = float4(dir, 2.5);\n"
2205 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2206 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2207 " float3 stc = float3(proj.xy * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2208 " stc += float3(vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.y, ShadowMap_Parameters.z);\n"
2213 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
2215 "#ifdef USESHADOWMAPCUBE\n"
2216 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2218 " float3 adir = abs(dir);\n"
2219 " return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2223 "# ifdef USESHADOWMAPRECT\n"
2224 "#ifdef USESHADOWMAPVSDCT\n"
2225 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2227 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2230 "#ifdef USESHADOWMAPVSDCT\n"
2231 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2233 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2236 "# ifdef USESHADOWSAMPLER\n"
2238 "# ifdef USESHADOWMAPPCF\n"
2239 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2240 " 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"
2242 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2247 "# ifdef USESHADOWMAPPCF\n"
2248 "# if USESHADOWMAPPCF > 1\n"
2249 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2250 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2251 " 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"
2252 " 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"
2253 " 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"
2254 " 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"
2255 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2256 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2258 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2259 " float2 offset = frac(shadowmaptc.xy);\n"
2260 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2261 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2262 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2263 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2264 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2267 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2271 "# ifdef USESHADOWMAPORTHO\n"
2272 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2279 "# ifdef USESHADOWMAP2D\n"
2280 "#ifdef USESHADOWMAPVSDCT\n"
2281 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2283 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2286 "#ifdef USESHADOWMAPVSDCT\n"
2287 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2289 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2293 "# ifdef USESHADOWSAMPLER\n"
2294 "# ifdef USESHADOWMAPPCF\n"
2295 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
2296 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2297 " 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"
2299 " f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2302 "# ifdef USESHADOWMAPPCF\n"
2303 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2304 "# ifdef GL_ARB_texture_gather\n"
2305 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2307 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2309 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2310 " center *= ShadowMap_TextureScale;\n"
2311 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2312 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2313 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2314 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2315 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2316 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2317 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2319 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale) \n"
2320 "# if USESHADOWMAPPCF > 1\n"
2321 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2322 " center *= ShadowMap_TextureScale;\n"
2323 " 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"
2324 " 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"
2325 " 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"
2326 " 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"
2327 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2328 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2330 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2331 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2332 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2333 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2334 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2335 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2339 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2342 "# ifdef USESHADOWMAPORTHO\n"
2343 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2350 "# ifdef USESHADOWMAPCUBE\n"
2351 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2353 " // apply depth texture cubemap as light filter\n"
2354 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2356 "# ifdef USESHADOWSAMPLER\n"
2357 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2359 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2364 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2365 "#endif // FRAGMENT_SHADER\n"
2370 "#ifdef MODE_DEFERREDGEOMETRY\n"
2371 "#ifdef VERTEX_SHADER\n"
2374 "float4 gl_Vertex : POSITION,\n"
2375 "uniform float4x4 ModelViewProjectionMatrix,\n"
2376 "#ifdef USEVERTEXTEXTUREBLEND\n"
2377 "float4 gl_Color : COLOR0,\n"
2379 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2380 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2381 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2382 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2383 "uniform float4x4 TexMatrix,\n"
2384 "#ifdef USEVERTEXTEXTUREBLEND\n"
2385 "uniform float4x4 BackgroundTexMatrix,\n"
2387 "uniform float4x4 ModelViewMatrix,\n"
2388 "#ifdef USEOFFSETMAPPING\n"
2389 "uniform float3 EyePosition,\n"
2391 "out float4 gl_Position : POSITION,\n"
2392 "out float4 gl_FrontColor : COLOR,\n"
2393 "out float4 TexCoordBoth : TEXCOORD0,\n"
2394 "#ifdef USEOFFSETMAPPING\n"
2395 "out float3 EyeVector : TEXCOORD2,\n"
2397 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2398 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2399 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2402 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2403 "#ifdef USEVERTEXTEXTUREBLEND\n"
2404 " gl_FrontColor = gl_Color;\n"
2405 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2408 " // transform unnormalized eye direction into tangent space\n"
2409 "#ifdef USEOFFSETMAPPING\n"
2410 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2411 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2412 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2413 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2416 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2417 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2418 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2419 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2421 "#endif // VERTEX_SHADER\n"
2423 "#ifdef FRAGMENT_SHADER\n"
2426 "float4 TexCoordBoth : TEXCOORD0,\n"
2427 "float3 EyeVector : TEXCOORD2,\n"
2428 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2429 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2430 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2431 "uniform sampler2D Texture_Normal,\n"
2432 "#ifdef USEALPHAKILL\n"
2433 "uniform sampler2D Texture_Color,\n"
2435 "uniform sampler2D Texture_Gloss,\n"
2436 "#ifdef USEVERTEXTEXTUREBLEND\n"
2437 "uniform sampler2D Texture_SecondaryNormal,\n"
2438 "uniform sampler2D Texture_SecondaryGloss,\n"
2440 "#ifdef USEOFFSETMAPPING\n"
2441 "uniform float OffsetMapping_Scale,\n"
2443 "uniform half SpecularPower,\n"
2444 "out float4 gl_FragColor : COLOR\n"
2447 " float2 TexCoord = TexCoordBoth.xy;\n"
2448 "#ifdef USEOFFSETMAPPING\n"
2449 " // apply offsetmapping\n"
2450 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2451 "#define TexCoord TexCoordOffset\n"
2454 "#ifdef USEALPHAKILL\n"
2455 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2459 "#ifdef USEVERTEXTEXTUREBLEND\n"
2460 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2461 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2462 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2463 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2466 "#ifdef USEVERTEXTEXTUREBLEND\n"
2467 " float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2468 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2470 " float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2471 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2474 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2476 "#endif // FRAGMENT_SHADER\n"
2477 "#else // !MODE_DEFERREDGEOMETRY\n"
2482 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2483 "#ifdef VERTEX_SHADER\n"
2486 "float4 gl_Vertex : POSITION,\n"
2487 "uniform float4x4 ModelViewProjectionMatrix,\n"
2488 "uniform float4x4 ModelViewMatrix,\n"
2489 "out float4 gl_Position : POSITION,\n"
2490 "out float4 ModelViewPosition : TEXCOORD0\n"
2493 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2494 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2496 "#endif // VERTEX_SHADER\n"
2498 "#ifdef FRAGMENT_SHADER\n"
2501 "float2 Pixel : WPOS,\n"
2502 "float4 ModelViewPosition : TEXCOORD0,\n"
2503 "uniform float4x4 ViewToLight,\n"
2504 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2505 "uniform float3 LightPosition,\n"
2506 "uniform half2 PixelToScreenTexCoord,\n"
2507 "uniform half3 DeferredColor_Ambient,\n"
2508 "uniform half3 DeferredColor_Diffuse,\n"
2509 "#ifdef USESPECULAR\n"
2510 "uniform half3 DeferredColor_Specular,\n"
2511 "uniform half SpecularPower,\n"
2513 "uniform sampler2D Texture_Attenuation,\n"
2514 "uniform sampler2D Texture_ScreenDepth,\n"
2515 "uniform sampler2D Texture_ScreenNormalMap,\n"
2517 "#ifdef USESHADOWMAPRECT\n"
2518 "# ifdef USESHADOWSAMPLER\n"
2519 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2521 "uniform samplerRECT Texture_ShadowMapRect,\n"
2525 "#ifdef USESHADOWMAP2D\n"
2526 "# ifdef USESHADOWSAMPLER\n"
2527 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2529 "uniform sampler2D Texture_ShadowMap2D,\n"
2533 "#ifdef USESHADOWMAPVSDCT\n"
2534 "uniform samplerCUBE Texture_CubeProjection,\n"
2537 "#ifdef USESHADOWMAPCUBE\n"
2538 "# ifdef USESHADOWSAMPLER\n"
2539 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2541 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2545 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2546 "uniform float2 ShadowMap_TextureScale,\n"
2547 "uniform float4 ShadowMap_Parameters,\n"
2550 "out float4 gl_FragData0 : COLOR0,\n"
2551 "out float4 gl_FragData1 : COLOR1\n"
2554 " // calculate viewspace pixel position\n"
2555 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2556 " ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2557 " float3 position;\n"
2558 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2559 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2560 " // decode viewspace pixel normal\n"
2561 " half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2562 " half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2563 " // surfacenormal = pixel normal in viewspace\n"
2564 " // LightVector = pixel to light in viewspace\n"
2565 " // CubeVector = position in lightspace\n"
2566 " // eyevector = pixel to view in viewspace\n"
2567 " float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2568 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2569 "#ifdef USEDIFFUSE\n"
2570 " // calculate diffuse shading\n"
2571 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2572 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2574 "#ifdef USESPECULAR\n"
2575 " // calculate directional shading\n"
2576 " float3 eyevector = position * -1.0;\n"
2577 "# ifdef USEEXACTSPECULARMATH\n"
2578 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2580 " half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2581 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2585 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2586 " fade *= ShadowMapCompare(CubeVector,\n"
2587 "# if defined(USESHADOWMAP2D)\n"
2588 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2590 "# if defined(USESHADOWMAPRECT)\n"
2591 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2593 "# if defined(USESHADOWMAPCUBE)\n"
2594 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2597 "#ifdef USESHADOWMAPVSDCT\n"
2598 ", Texture_CubeProjection\n"
2603 "#ifdef USEDIFFUSE\n"
2604 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2606 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2608 "#ifdef USESPECULAR\n"
2609 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2611 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2614 "# ifdef USECUBEFILTER\n"
2615 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2616 " gl_FragData0.rgb *= cubecolor;\n"
2617 " gl_FragData1.rgb *= cubecolor;\n"
2620 "#endif // FRAGMENT_SHADER\n"
2621 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2626 "#ifdef VERTEX_SHADER\n"
2629 "float4 gl_Vertex : POSITION,\n"
2630 "uniform float4x4 ModelViewProjectionMatrix,\n"
2631 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2632 "float4 gl_Color : COLOR0,\n"
2634 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2635 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2636 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2637 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2638 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2640 "uniform float3 EyePosition,\n"
2641 "uniform float4x4 TexMatrix,\n"
2642 "#ifdef USEVERTEXTEXTUREBLEND\n"
2643 "uniform float4x4 BackgroundTexMatrix,\n"
2645 "#ifdef MODE_LIGHTSOURCE\n"
2646 "uniform float4x4 ModelToLight,\n"
2648 "#ifdef MODE_LIGHTSOURCE\n"
2649 "uniform float3 LightPosition,\n"
2651 "#ifdef MODE_LIGHTDIRECTION\n"
2652 "uniform float3 LightDir,\n"
2654 "uniform float4 FogPlane,\n"
2655 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2656 "uniform float3 LightPosition,\n"
2658 "#ifdef USESHADOWMAPORTHO\n"
2659 "uniform float4x4 ShadowMapMatrix,\n"
2662 "out float4 gl_FrontColor : COLOR,\n"
2663 "out float4 TexCoordBoth : TEXCOORD0,\n"
2664 "#ifdef USELIGHTMAP\n"
2665 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2667 "#ifdef USEEYEVECTOR\n"
2668 "out float3 EyeVector : TEXCOORD2,\n"
2670 "#ifdef USEREFLECTION\n"
2671 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2674 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2676 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2677 "out float3 LightVector : TEXCOORD5,\n"
2679 "#ifdef MODE_LIGHTSOURCE\n"
2680 "out float3 CubeVector : TEXCOORD3,\n"
2682 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2683 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2684 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2685 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2687 "#ifdef USESHADOWMAPORTHO\n"
2688 "out float3 ShadowMapTC : TEXCOORD8,\n"
2690 "out float4 gl_Position : POSITION\n"
2693 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2694 " gl_FrontColor = gl_Color;\n"
2696 " // copy the surface texcoord\n"
2697 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2698 "#ifdef USEVERTEXTEXTUREBLEND\n"
2699 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2701 "#ifdef USELIGHTMAP\n"
2702 " TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2705 "#ifdef MODE_LIGHTSOURCE\n"
2706 " // transform vertex position into light attenuation/cubemap space\n"
2707 " // (-1 to +1 across the light box)\n"
2708 " CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2710 "# ifdef USEDIFFUSE\n"
2711 " // transform unnormalized light direction into tangent space\n"
2712 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2713 " // normalize it per pixel)\n"
2714 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2715 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2716 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2717 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2721 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2722 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2723 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2724 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2727 " // transform unnormalized eye direction into tangent space\n"
2728 "#ifdef USEEYEVECTOR\n"
2729 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2730 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2731 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2732 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2736 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2737 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2740 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2741 " VectorS = gl_MultiTexCoord1.xyz;\n"
2742 " VectorT = gl_MultiTexCoord2.xyz;\n"
2743 " VectorR = gl_MultiTexCoord3.xyz;\n"
2746 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2747 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2749 "#ifdef USESHADOWMAPORTHO\n"
2750 " ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2753 "#ifdef USEREFLECTION\n"
2754 " ModelViewProjectionPosition = gl_Position;\n"
2757 "#endif // VERTEX_SHADER\n"
2762 "#ifdef FRAGMENT_SHADER\n"
2765 "#ifdef USEDEFERREDLIGHTMAP\n"
2766 "float2 Pixel : WPOS,\n"
2768 "float4 gl_FrontColor : COLOR,\n"
2769 "float4 TexCoordBoth : TEXCOORD0,\n"
2770 "#ifdef USELIGHTMAP\n"
2771 "float2 TexCoordLightmap : TEXCOORD1,\n"
2773 "#ifdef USEEYEVECTOR\n"
2774 "float3 EyeVector : TEXCOORD2,\n"
2776 "#ifdef USEREFLECTION\n"
2777 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2780 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2782 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2783 "float3 LightVector : TEXCOORD5,\n"
2785 "#ifdef MODE_LIGHTSOURCE\n"
2786 "float3 CubeVector : TEXCOORD3,\n"
2788 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2789 "float4 ModelViewPosition : TEXCOORD0,\n"
2791 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2792 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2793 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2794 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2796 "#ifdef USESHADOWMAPORTHO\n"
2797 "float3 ShadowMapTC : TEXCOORD8\n"
2800 "uniform sampler2D Texture_Normal,\n"
2801 "uniform sampler2D Texture_Color,\n"
2802 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2803 "uniform sampler2D Texture_Gloss,\n"
2806 "uniform sampler2D Texture_Glow,\n"
2808 "#ifdef USEVERTEXTEXTUREBLEND\n"
2809 "uniform sampler2D Texture_SecondaryNormal,\n"
2810 "uniform sampler2D Texture_SecondaryColor,\n"
2811 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2812 "uniform sampler2D Texture_SecondaryGloss,\n"
2815 "uniform sampler2D Texture_SecondaryGlow,\n"
2818 "#ifdef USECOLORMAPPING\n"
2819 "uniform sampler2D Texture_Pants,\n"
2820 "uniform sampler2D Texture_Shirt,\n"
2823 "uniform sampler2D Texture_FogMask,\n"
2825 "#ifdef USELIGHTMAP\n"
2826 "uniform sampler2D Texture_Lightmap,\n"
2828 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2829 "uniform sampler2D Texture_Deluxemap,\n"
2831 "#ifdef USEREFLECTION\n"
2832 "uniform sampler2D Texture_Reflection,\n"
2835 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2836 "uniform sampler2D Texture_ScreenDepth,\n"
2837 "uniform sampler2D Texture_ScreenNormalMap,\n"
2839 "#ifdef USEDEFERREDLIGHTMAP\n"
2840 "uniform sampler2D Texture_ScreenDiffuse,\n"
2841 "uniform sampler2D Texture_ScreenSpecular,\n"
2844 "#ifdef USECOLORMAPPING\n"
2845 "uniform half3 Color_Pants,\n"
2846 "uniform half3 Color_Shirt,\n"
2849 "uniform float3 FogColor,\n"
2850 "uniform float FogRangeRecip,\n"
2851 "uniform float FogPlaneViewDist,\n"
2852 "uniform float FogHeightFade,\n"
2855 "#ifdef USEOFFSETMAPPING\n"
2856 "uniform float OffsetMapping_Scale,\n"
2859 "#ifdef USEDEFERREDLIGHTMAP\n"
2860 "uniform half2 PixelToScreenTexCoord,\n"
2861 "uniform half3 DeferredMod_Diffuse,\n"
2862 "uniform half3 DeferredMod_Specular,\n"
2864 "uniform half3 Color_Ambient,\n"
2865 "uniform half3 Color_Diffuse,\n"
2866 "uniform half3 Color_Specular,\n"
2867 "uniform half SpecularPower,\n"
2869 "uniform half3 Color_Glow,\n"
2871 "uniform half Alpha,\n"
2872 "#ifdef USEREFLECTION\n"
2873 "uniform float4 DistortScaleRefractReflect,\n"
2874 "uniform float4 ScreenScaleRefractReflect,\n"
2875 "uniform float4 ScreenCenterRefractReflect,\n"
2876 "uniform half4 ReflectColor,\n"
2878 "#ifdef USEREFLECTCUBE\n"
2879 "uniform float4x4 ModelToReflectCube,\n"
2880 "uniform sampler2D Texture_ReflectMask,\n"
2881 "uniform samplerCUBE Texture_ReflectCube,\n"
2883 "#ifdef MODE_LIGHTDIRECTION\n"
2884 "uniform half3 LightColor,\n"
2886 "#ifdef MODE_LIGHTSOURCE\n"
2887 "uniform half3 LightColor,\n"
2890 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2891 "uniform sampler2D Texture_Attenuation,\n"
2892 "uniform samplerCUBE Texture_Cube,\n"
2895 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2897 "#ifdef USESHADOWMAPRECT\n"
2898 "# ifdef USESHADOWSAMPLER\n"
2899 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2901 "uniform samplerRECT Texture_ShadowMapRect,\n"
2905 "#ifdef USESHADOWMAP2D\n"
2906 "# ifdef USESHADOWSAMPLER\n"
2907 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2909 "uniform sampler2D Texture_ShadowMap2D,\n"
2913 "#ifdef USESHADOWMAPVSDCT\n"
2914 "uniform samplerCUBE Texture_CubeProjection,\n"
2917 "#ifdef USESHADOWMAPCUBE\n"
2918 "# ifdef USESHADOWSAMPLER\n"
2919 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2921 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2925 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2926 "uniform float2 ShadowMap_TextureScale,\n"
2927 "uniform float4 ShadowMap_Parameters,\n"
2929 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2931 "out float4 gl_FragColor : COLOR\n"
2934 " float2 TexCoord = TexCoordBoth.xy;\n"
2935 "#ifdef USEVERTEXTEXTUREBLEND\n"
2936 " float2 TexCoord2 = TexCoordBoth.zw;\n"
2938 "#ifdef USEOFFSETMAPPING\n"
2939 " // apply offsetmapping\n"
2940 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2941 "#define TexCoord TexCoordOffset\n"
2944 " // combine the diffuse textures (base, pants, shirt)\n"
2945 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2946 "#ifdef USEALPHAKILL\n"
2947 " if (color.a < 0.5)\n"
2950 " color.a *= Alpha;\n"
2951 "#ifdef USECOLORMAPPING\n"
2952 " color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2954 "#ifdef USEVERTEXTEXTUREBLEND\n"
2955 " float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2956 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2957 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2958 " color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2960 " //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2963 " // get the surface normal\n"
2964 "#ifdef USEVERTEXTEXTUREBLEND\n"
2965 " half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2967 " half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2970 " // get the material colors\n"
2971 " half3 diffusetex = color.rgb;\n"
2972 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2973 "# ifdef USEVERTEXTEXTUREBLEND\n"
2974 " half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2976 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
2980 "#ifdef USEREFLECTCUBE\n"
2981 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
2982 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
2983 " vec3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
2984 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
2990 "#ifdef MODE_LIGHTSOURCE\n"
2991 " // light source\n"
2992 "#ifdef USEDIFFUSE\n"
2993 " half3 lightnormal = half3(normalize(LightVector));\n"
2994 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2995 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2996 "#ifdef USESPECULAR\n"
2997 "#ifdef USEEXACTSPECULARMATH\n"
2998 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3000 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3001 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3003 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3006 " color.rgb = diffusetex * Color_Ambient;\n"
3008 " color.rgb *= LightColor;\n"
3009 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3010 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3011 " color.rgb *= ShadowMapCompare(CubeVector,\n"
3012 "# if defined(USESHADOWMAP2D)\n"
3013 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3015 "# if defined(USESHADOWMAPRECT)\n"
3016 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3018 "# if defined(USESHADOWMAPCUBE)\n"
3019 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3022 "#ifdef USESHADOWMAPVSDCT\n"
3023 ", Texture_CubeProjection\n"
3028 "# ifdef USECUBEFILTER\n"
3029 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3031 "#endif // MODE_LIGHTSOURCE\n"
3036 "#ifdef MODE_LIGHTDIRECTION\n"
3038 "#ifdef USEDIFFUSE\n"
3039 " half3 lightnormal = half3(normalize(LightVector));\n"
3041 "#define lightcolor LightColor\n"
3042 "#endif // MODE_LIGHTDIRECTION\n"
3043 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3045 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3046 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3047 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3048 " // convert modelspace light vector to tangentspace\n"
3049 " half3 lightnormal;\n"
3050 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3051 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3052 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3053 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3054 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3055 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3056 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3057 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3058 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3059 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3060 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3061 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3062 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3063 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3064 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3066 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3067 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3068 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3074 "#ifdef MODE_LIGHTMAP\n"
3075 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3076 "#endif // MODE_LIGHTMAP\n"
3077 "#ifdef MODE_VERTEXCOLOR\n"
3078 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3079 "#endif // MODE_VERTEXCOLOR\n"
3080 "#ifdef MODE_FLATCOLOR\n"
3081 " color.rgb = diffusetex * Color_Ambient;\n"
3082 "#endif // MODE_FLATCOLOR\n"
3088 "# ifdef USEDIFFUSE\n"
3089 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3090 "# ifdef USESPECULAR\n"
3091 "# ifdef USEEXACTSPECULARMATH\n"
3092 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3094 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3095 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3097 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3099 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3102 " color.rgb = diffusetex * Color_Ambient;\n"
3106 "#ifdef USESHADOWMAPORTHO\n"
3107 " color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3108 "# if defined(USESHADOWMAP2D)\n"
3109 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3111 "# if defined(USESHADOWMAPRECT)\n"
3112 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3117 "#ifdef USEDEFERREDLIGHTMAP\n"
3118 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3119 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3120 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3124 "#ifdef USEVERTEXTEXTUREBLEND\n"
3125 " color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3127 " color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3132 "#ifdef MODE_LIGHTSOURCE\n"
3133 " color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3135 " color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3139 " // 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"
3140 "#ifdef USEREFLECTION\n"
3141 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3142 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3143 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3144 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3145 " // FIXME temporary hack to detect the case that the reflection\n"
3146 " // gets blackened at edges due to leaving the area that contains actual\n"
3148 " // Remove this 'ack once we have a better way to stop this thing from\n"
3150 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3151 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3152 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3153 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3154 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3155 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3158 " gl_FragColor = float4(color);\n"
3160 "#endif // FRAGMENT_SHADER\n"
3162 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3163 "#endif // !MODE_DEFERREDGEOMETRY\n"
3164 "#endif // !MODE_WATER\n"
3165 "#endif // !MODE_REFRACTION\n"
3166 "#endif // !MODE_BLOOMBLUR\n"
3167 "#endif // !MODE_GENERIC\n"
3168 "#endif // !MODE_POSTPROCESS\n"
3169 "#endif // !MODE_SHOWDEPTH\n"
3170 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3173 char *glslshaderstring = NULL;
3174 char *cgshaderstring = NULL;
3176 //=======================================================================================================================================================
3178 typedef struct shaderpermutationinfo_s
3180 const char *pretext;
3183 shaderpermutationinfo_t;
3185 typedef struct shadermodeinfo_s
3187 const char *vertexfilename;
3188 const char *geometryfilename;
3189 const char *fragmentfilename;
3190 const char *pretext;
3195 typedef enum shaderpermutation_e
3197 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3198 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3199 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3200 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3201 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3202 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3203 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3204 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3205 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3206 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3207 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3208 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3209 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3210 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3211 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3212 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3213 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3214 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3215 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3216 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3217 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3218 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3219 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3220 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3221 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3222 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3223 SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3224 SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3225 SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3226 SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3228 shaderpermutation_t;
3230 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3231 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3233 {"#define USEDIFFUSE\n", " diffuse"},
3234 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3235 {"#define USEVIEWTINT\n", " viewtint"},
3236 {"#define USECOLORMAPPING\n", " colormapping"},
3237 {"#define USESATURATION\n", " saturation"},
3238 {"#define USEFOGINSIDE\n", " foginside"},
3239 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3240 {"#define USEGAMMARAMPS\n", " gammaramps"},
3241 {"#define USECUBEFILTER\n", " cubefilter"},
3242 {"#define USEGLOW\n", " glow"},
3243 {"#define USEBLOOM\n", " bloom"},
3244 {"#define USESPECULAR\n", " specular"},
3245 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3246 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3247 {"#define USEREFLECTION\n", " reflection"},
3248 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3249 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3250 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3251 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3252 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3253 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3254 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3255 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3256 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3257 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3258 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3259 {"#define USEALPHAKILL\n", " alphakill"},
3260 {"#define USEREFLECTCUBE\n", " reflectcube"},
3263 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3264 typedef enum shadermode_e
3266 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3267 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3268 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3269 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3270 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3271 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3272 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3273 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3274 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3275 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3276 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3277 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3278 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3279 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3280 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3285 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3286 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3288 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3289 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3290 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3291 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3292 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3293 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3294 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3295 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3296 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3297 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3298 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3299 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3300 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3301 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3302 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3306 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3308 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3309 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3310 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3311 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3312 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3313 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3314 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3315 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3316 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3317 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3318 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3319 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3320 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3321 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3322 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3326 struct r_glsl_permutation_s;
3327 typedef struct r_glsl_permutation_s
3329 /// hash lookup data
3330 struct r_glsl_permutation_s *hashnext;
3332 unsigned int permutation;
3334 /// indicates if we have tried compiling this permutation already
3336 /// 0 if compilation failed
3338 /// locations of detected uniforms in program object, or -1 if not found
3339 int loc_Texture_First;
3340 int loc_Texture_Second;
3341 int loc_Texture_GammaRamps;
3342 int loc_Texture_Normal;
3343 int loc_Texture_Color;
3344 int loc_Texture_Gloss;
3345 int loc_Texture_Glow;
3346 int loc_Texture_SecondaryNormal;
3347 int loc_Texture_SecondaryColor;
3348 int loc_Texture_SecondaryGloss;
3349 int loc_Texture_SecondaryGlow;
3350 int loc_Texture_Pants;
3351 int loc_Texture_Shirt;
3352 int loc_Texture_FogMask;
3353 int loc_Texture_Lightmap;
3354 int loc_Texture_Deluxemap;
3355 int loc_Texture_Attenuation;
3356 int loc_Texture_Cube;
3357 int loc_Texture_Refraction;
3358 int loc_Texture_Reflection;
3359 int loc_Texture_ShadowMapRect;
3360 int loc_Texture_ShadowMapCube;
3361 int loc_Texture_ShadowMap2D;
3362 int loc_Texture_CubeProjection;
3363 int loc_Texture_ScreenDepth;
3364 int loc_Texture_ScreenNormalMap;
3365 int loc_Texture_ScreenDiffuse;
3366 int loc_Texture_ScreenSpecular;
3367 int loc_Texture_ReflectMask;
3368 int loc_Texture_ReflectCube;
3370 int loc_BloomBlur_Parameters;
3372 int loc_Color_Ambient;
3373 int loc_Color_Diffuse;
3374 int loc_Color_Specular;
3376 int loc_Color_Pants;
3377 int loc_Color_Shirt;
3378 int loc_DeferredColor_Ambient;
3379 int loc_DeferredColor_Diffuse;
3380 int loc_DeferredColor_Specular;
3381 int loc_DeferredMod_Diffuse;
3382 int loc_DeferredMod_Specular;
3383 int loc_DistortScaleRefractReflect;
3384 int loc_EyePosition;
3386 int loc_FogHeightFade;
3388 int loc_FogPlaneViewDist;
3389 int loc_FogRangeRecip;
3392 int loc_LightPosition;
3393 int loc_OffsetMapping_Scale;
3395 int loc_ReflectColor;
3396 int loc_ReflectFactor;
3397 int loc_ReflectOffset;
3398 int loc_RefractColor;
3400 int loc_ScreenCenterRefractReflect;
3401 int loc_ScreenScaleRefractReflect;
3402 int loc_ScreenToDepth;
3403 int loc_ShadowMap_Parameters;
3404 int loc_ShadowMap_TextureScale;
3405 int loc_SpecularPower;
3410 int loc_ViewTintColor;
3411 int loc_ViewToLight;
3412 int loc_ModelToLight;
3414 int loc_BackgroundTexMatrix;
3415 int loc_ModelViewProjectionMatrix;
3416 int loc_ModelViewMatrix;
3417 int loc_PixelToScreenTexCoord;
3418 int loc_ModelToReflectCube;
3419 int loc_ShadowMapMatrix;
3421 r_glsl_permutation_t;
3423 #define SHADERPERMUTATION_HASHSIZE 256
3425 /// information about each possible shader permutation
3426 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3427 /// currently selected permutation
3428 r_glsl_permutation_t *r_glsl_permutation;
3429 /// storage for permutations linked in the hash table
3430 memexpandablearray_t r_glsl_permutationarray;
3432 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3434 //unsigned int hashdepth = 0;
3435 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3436 r_glsl_permutation_t *p;
3437 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3439 if (p->mode == mode && p->permutation == permutation)
3441 //if (hashdepth > 10)
3442 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3447 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3449 p->permutation = permutation;
3450 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3451 r_glsl_permutationhash[mode][hashindex] = p;
3452 //if (hashdepth > 10)
3453 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3457 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3460 if (!filename || !filename[0])
3462 if (!strcmp(filename, "glsl/default.glsl"))
3464 if (!glslshaderstring)
3466 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3467 if (glslshaderstring)
3468 Con_DPrintf("Loading shaders from file %s...\n", filename);
3470 glslshaderstring = (char *)builtinshaderstring;
3472 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3473 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3474 return shaderstring;
3476 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3479 if (printfromdisknotice)
3480 Con_DPrintf("from disk %s... ", filename);
3481 return shaderstring;
3483 return shaderstring;
3486 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3489 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3490 int vertstrings_count = 0;
3491 int geomstrings_count = 0;
3492 int fragstrings_count = 0;
3493 char *vertexstring, *geometrystring, *fragmentstring;
3494 const char *vertstrings_list[32+3];
3495 const char *geomstrings_list[32+3];
3496 const char *fragstrings_list[32+3];
3497 char permutationname[256];
3504 permutationname[0] = 0;
3505 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3506 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3507 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3509 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3511 // the first pretext is which type of shader to compile as
3512 // (later these will all be bound together as a program object)
3513 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3514 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3515 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3517 // the second pretext is the mode (for example a light source)
3518 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3519 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3520 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3521 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3523 // now add all the permutation pretexts
3524 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3526 if (permutation & (1<<i))
3528 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3529 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3530 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3531 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3535 // keep line numbers correct
3536 vertstrings_list[vertstrings_count++] = "\n";
3537 geomstrings_list[geomstrings_count++] = "\n";
3538 fragstrings_list[fragstrings_count++] = "\n";
3542 // now append the shader text itself
3543 vertstrings_list[vertstrings_count++] = vertexstring;
3544 geomstrings_list[geomstrings_count++] = geometrystring;
3545 fragstrings_list[fragstrings_count++] = fragmentstring;
3547 // if any sources were NULL, clear the respective list
3549 vertstrings_count = 0;
3550 if (!geometrystring)
3551 geomstrings_count = 0;
3552 if (!fragmentstring)
3553 fragstrings_count = 0;
3555 // compile the shader program
3556 if (vertstrings_count + geomstrings_count + fragstrings_count)
3557 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3561 qglUseProgramObjectARB(p->program);CHECKGLERROR
3562 // look up all the uniform variable names we care about, so we don't
3563 // have to look them up every time we set them
3565 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3566 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3567 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3568 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3569 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3570 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3571 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3572 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3573 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3574 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3575 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3576 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3577 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3578 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3579 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3580 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3581 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3582 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3583 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3584 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3585 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3586 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3587 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3588 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3589 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3590 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3591 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3592 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3593 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3594 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3595 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3596 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3597 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3598 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3599 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3600 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3601 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3602 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3603 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3604 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3605 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3606 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3607 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3608 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3609 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3610 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3611 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3612 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3613 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3614 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3615 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3616 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3617 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3618 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3619 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3620 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3621 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3622 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3623 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3624 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3625 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3626 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3627 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3628 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3629 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3630 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3631 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3632 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3633 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3634 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3635 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3636 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3637 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3638 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3639 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3640 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3641 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3642 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3643 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3644 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3645 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3646 // initialize the samplers to refer to the texture units we use
3647 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3648 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3649 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3650 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3651 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3652 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3653 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3654 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3655 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3656 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3657 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3658 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3659 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3660 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3661 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3662 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3663 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3664 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3665 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3666 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3667 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3668 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3669 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3670 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3671 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3672 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3673 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3674 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3675 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3676 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3678 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3681 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3685 Mem_Free(vertexstring);
3687 Mem_Free(geometrystring);
3689 Mem_Free(fragmentstring);
3692 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3694 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3695 if (r_glsl_permutation != perm)
3697 r_glsl_permutation = perm;
3698 if (!r_glsl_permutation->program)
3700 if (!r_glsl_permutation->compiled)
3701 R_GLSL_CompilePermutation(perm, mode, permutation);
3702 if (!r_glsl_permutation->program)
3704 // remove features until we find a valid permutation
3706 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3708 // reduce i more quickly whenever it would not remove any bits
3709 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3710 if (!(permutation & j))
3713 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3714 if (!r_glsl_permutation->compiled)
3715 R_GLSL_CompilePermutation(perm, mode, permutation);
3716 if (r_glsl_permutation->program)
3719 if (i >= SHADERPERMUTATION_COUNT)
3721 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3722 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3723 qglUseProgramObjectARB(0);CHECKGLERROR
3724 return; // no bit left to clear, entire mode is broken
3729 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3731 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3732 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3733 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3737 #include <Cg/cgGL.h>
3738 struct r_cg_permutation_s;
3739 typedef struct r_cg_permutation_s
3741 /// hash lookup data
3742 struct r_cg_permutation_s *hashnext;
3744 unsigned int permutation;
3746 /// indicates if we have tried compiling this permutation already
3748 /// 0 if compilation failed
3751 /// locations of detected parameters in programs, or NULL if not found
3752 CGparameter vp_EyePosition;
3753 CGparameter vp_FogPlane;
3754 CGparameter vp_LightDir;
3755 CGparameter vp_LightPosition;
3756 CGparameter vp_ModelToLight;
3757 CGparameter vp_TexMatrix;
3758 CGparameter vp_BackgroundTexMatrix;
3759 CGparameter vp_ModelViewProjectionMatrix;
3760 CGparameter vp_ModelViewMatrix;
3761 CGparameter vp_ShadowMapMatrix;
3763 CGparameter fp_Texture_First;
3764 CGparameter fp_Texture_Second;
3765 CGparameter fp_Texture_GammaRamps;
3766 CGparameter fp_Texture_Normal;
3767 CGparameter fp_Texture_Color;
3768 CGparameter fp_Texture_Gloss;
3769 CGparameter fp_Texture_Glow;
3770 CGparameter fp_Texture_SecondaryNormal;
3771 CGparameter fp_Texture_SecondaryColor;
3772 CGparameter fp_Texture_SecondaryGloss;
3773 CGparameter fp_Texture_SecondaryGlow;
3774 CGparameter fp_Texture_Pants;
3775 CGparameter fp_Texture_Shirt;
3776 CGparameter fp_Texture_FogMask;
3777 CGparameter fp_Texture_Lightmap;
3778 CGparameter fp_Texture_Deluxemap;
3779 CGparameter fp_Texture_Attenuation;
3780 CGparameter fp_Texture_Cube;
3781 CGparameter fp_Texture_Refraction;
3782 CGparameter fp_Texture_Reflection;
3783 CGparameter fp_Texture_ShadowMapRect;
3784 CGparameter fp_Texture_ShadowMapCube;
3785 CGparameter fp_Texture_ShadowMap2D;
3786 CGparameter fp_Texture_CubeProjection;
3787 CGparameter fp_Texture_ScreenDepth;
3788 CGparameter fp_Texture_ScreenNormalMap;
3789 CGparameter fp_Texture_ScreenDiffuse;
3790 CGparameter fp_Texture_ScreenSpecular;
3791 CGparameter fp_Texture_ReflectMask;
3792 CGparameter fp_Texture_ReflectCube;
3793 CGparameter fp_Alpha;
3794 CGparameter fp_BloomBlur_Parameters;
3795 CGparameter fp_ClientTime;
3796 CGparameter fp_Color_Ambient;
3797 CGparameter fp_Color_Diffuse;
3798 CGparameter fp_Color_Specular;
3799 CGparameter fp_Color_Glow;
3800 CGparameter fp_Color_Pants;
3801 CGparameter fp_Color_Shirt;
3802 CGparameter fp_DeferredColor_Ambient;
3803 CGparameter fp_DeferredColor_Diffuse;
3804 CGparameter fp_DeferredColor_Specular;
3805 CGparameter fp_DeferredMod_Diffuse;
3806 CGparameter fp_DeferredMod_Specular;
3807 CGparameter fp_DistortScaleRefractReflect;
3808 CGparameter fp_EyePosition;
3809 CGparameter fp_FogColor;
3810 CGparameter fp_FogHeightFade;
3811 CGparameter fp_FogPlane;
3812 CGparameter fp_FogPlaneViewDist;
3813 CGparameter fp_FogRangeRecip;
3814 CGparameter fp_LightColor;
3815 CGparameter fp_LightDir;
3816 CGparameter fp_LightPosition;
3817 CGparameter fp_OffsetMapping_Scale;
3818 CGparameter fp_PixelSize;
3819 CGparameter fp_ReflectColor;
3820 CGparameter fp_ReflectFactor;
3821 CGparameter fp_ReflectOffset;
3822 CGparameter fp_RefractColor;
3823 CGparameter fp_Saturation;
3824 CGparameter fp_ScreenCenterRefractReflect;
3825 CGparameter fp_ScreenScaleRefractReflect;
3826 CGparameter fp_ScreenToDepth;
3827 CGparameter fp_ShadowMap_Parameters;
3828 CGparameter fp_ShadowMap_TextureScale;
3829 CGparameter fp_SpecularPower;
3830 CGparameter fp_UserVec1;
3831 CGparameter fp_UserVec2;
3832 CGparameter fp_UserVec3;
3833 CGparameter fp_UserVec4;
3834 CGparameter fp_ViewTintColor;
3835 CGparameter fp_ViewToLight;
3836 CGparameter fp_PixelToScreenTexCoord;
3837 CGparameter fp_ModelToReflectCube;
3841 /// information about each possible shader permutation
3842 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3843 /// currently selected permutation
3844 r_cg_permutation_t *r_cg_permutation;
3845 /// storage for permutations linked in the hash table
3846 memexpandablearray_t r_cg_permutationarray;
3848 #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));}}
3850 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3852 //unsigned int hashdepth = 0;
3853 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3854 r_cg_permutation_t *p;
3855 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3857 if (p->mode == mode && p->permutation == permutation)
3859 //if (hashdepth > 10)
3860 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3865 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3867 p->permutation = permutation;
3868 p->hashnext = r_cg_permutationhash[mode][hashindex];
3869 r_cg_permutationhash[mode][hashindex] = p;
3870 //if (hashdepth > 10)
3871 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3875 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3878 if (!filename || !filename[0])
3880 if (!strcmp(filename, "cg/default.cg"))
3882 if (!cgshaderstring)
3884 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3886 Con_DPrintf("Loading shaders from file %s...\n", filename);
3888 cgshaderstring = (char *)builtincgshaderstring;
3890 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3891 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3892 return shaderstring;
3894 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3897 if (printfromdisknotice)
3898 Con_DPrintf("from disk %s... ", filename);
3899 return shaderstring;
3901 return shaderstring;
3904 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3906 // TODO: load or create .fp and .vp shader files
3909 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3912 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3913 int vertstrings_count = 0, vertstring_length = 0;
3914 int geomstrings_count = 0, geomstring_length = 0;
3915 int fragstrings_count = 0, fragstring_length = 0;
3917 char *vertexstring, *geometrystring, *fragmentstring;
3918 char *vertstring, *geomstring, *fragstring;
3919 const char *vertstrings_list[32+3];
3920 const char *geomstrings_list[32+3];
3921 const char *fragstrings_list[32+3];
3922 char permutationname[256];
3923 char cachename[256];
3924 CGprofile vertexProfile;
3925 CGprofile fragmentProfile;
3933 permutationname[0] = 0;
3935 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
3936 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3937 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3939 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3940 strlcat(cachename, "cg/", sizeof(cachename));
3942 // the first pretext is which type of shader to compile as
3943 // (later these will all be bound together as a program object)
3944 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3945 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3946 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3948 // the second pretext is the mode (for example a light source)
3949 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3950 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3951 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3952 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3953 strlcat(cachename, modeinfo->name, sizeof(cachename));
3955 // now add all the permutation pretexts
3956 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3958 if (permutation & (1<<i))
3960 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3961 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3962 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3963 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3964 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
3968 // keep line numbers correct
3969 vertstrings_list[vertstrings_count++] = "\n";
3970 geomstrings_list[geomstrings_count++] = "\n";
3971 fragstrings_list[fragstrings_count++] = "\n";
3975 // replace spaces in the cachename with _ characters
3976 for (i = 0;cachename[i];i++)
3977 if (cachename[i] == ' ')
3980 // now append the shader text itself
3981 vertstrings_list[vertstrings_count++] = vertexstring;
3982 geomstrings_list[geomstrings_count++] = geometrystring;
3983 fragstrings_list[fragstrings_count++] = fragmentstring;
3985 // if any sources were NULL, clear the respective list
3987 vertstrings_count = 0;
3988 if (!geometrystring)
3989 geomstrings_count = 0;
3990 if (!fragmentstring)
3991 fragstrings_count = 0;
3993 vertstring_length = 0;
3994 for (i = 0;i < vertstrings_count;i++)
3995 vertstring_length += strlen(vertstrings_list[i]);
3996 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3997 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3998 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4000 geomstring_length = 0;
4001 for (i = 0;i < geomstrings_count;i++)
4002 geomstring_length += strlen(geomstrings_list[i]);
4003 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4004 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4005 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4007 fragstring_length = 0;
4008 for (i = 0;i < fragstrings_count;i++)
4009 fragstring_length += strlen(fragstrings_list[i]);
4010 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4011 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4012 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4016 //vertexProfile = CG_PROFILE_ARBVP1;
4017 //fragmentProfile = CG_PROFILE_ARBFP1;
4018 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4019 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4020 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4021 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4022 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4025 // try to load the cached shader, or generate one
4026 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4028 // if caching failed, do a dynamic compile for now
4030 if (vertstring[0] && !p->vprogram)
4031 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4033 if (fragstring[0] && !p->fprogram)
4034 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4037 // look up all the uniform variable names we care about, so we don't
4038 // have to look them up every time we set them
4042 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4043 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4044 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4045 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4046 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4047 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4048 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4049 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4050 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4051 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4052 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4053 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4059 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4060 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4061 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4062 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4063 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4064 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4065 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4066 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4067 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4068 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4069 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4070 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4071 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4072 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4073 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4074 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4075 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4076 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4077 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4078 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4079 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4080 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4081 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4082 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4083 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4084 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4085 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4086 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4087 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4088 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4089 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4090 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4091 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4092 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4093 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4094 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4095 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4096 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4097 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4098 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4099 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4100 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4101 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4102 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4103 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4104 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4105 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4106 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4107 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4108 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4109 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4110 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4111 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4112 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4113 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4114 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4115 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4116 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4117 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4118 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4119 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4120 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4121 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4122 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4123 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4124 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4125 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4126 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4127 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4128 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4129 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4130 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4131 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4132 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4133 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4134 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4135 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4139 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4140 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4142 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4146 Mem_Free(vertstring);
4148 Mem_Free(geomstring);
4150 Mem_Free(fragstring);
4152 Mem_Free(vertexstring);
4154 Mem_Free(geometrystring);
4156 Mem_Free(fragmentstring);
4159 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4161 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4164 if (r_cg_permutation != perm)
4166 r_cg_permutation = perm;
4167 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4169 if (!r_cg_permutation->compiled)
4170 R_CG_CompilePermutation(perm, mode, permutation);
4171 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4173 // remove features until we find a valid permutation
4175 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4177 // reduce i more quickly whenever it would not remove any bits
4178 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4179 if (!(permutation & j))
4182 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4183 if (!r_cg_permutation->compiled)
4184 R_CG_CompilePermutation(perm, mode, permutation);
4185 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4188 if (i >= SHADERPERMUTATION_COUNT)
4190 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4191 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4192 return; // no bit left to clear, entire mode is broken
4198 if (r_cg_permutation->vprogram)
4200 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4201 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4202 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4206 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4207 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4209 if (r_cg_permutation->fprogram)
4211 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4212 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4213 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4217 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4218 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4222 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4223 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4224 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4227 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4229 cgGLSetTextureParameter(param, R_GetTexture(tex));
4230 cgGLEnableTextureParameter(param);
4234 void R_GLSL_Restart_f(void)
4236 unsigned int i, limit;
4237 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4238 Mem_Free(glslshaderstring);
4239 glslshaderstring = NULL;
4240 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4241 Mem_Free(cgshaderstring);
4242 cgshaderstring = NULL;
4243 switch(vid.renderpath)
4245 case RENDERPATH_GL20:
4247 r_glsl_permutation_t *p;
4248 r_glsl_permutation = NULL;
4249 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4250 for (i = 0;i < limit;i++)
4252 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4254 GL_Backend_FreeProgram(p->program);
4255 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4258 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4261 case RENDERPATH_CGGL:
4264 r_cg_permutation_t *p;
4265 r_cg_permutation = NULL;
4266 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4267 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4268 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4269 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4270 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4271 for (i = 0;i < limit;i++)
4273 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4276 cgDestroyProgram(p->vprogram);
4278 cgDestroyProgram(p->fprogram);
4279 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4282 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4286 case RENDERPATH_GL13:
4287 case RENDERPATH_GL11:
4292 void R_GLSL_DumpShader_f(void)
4297 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4300 FS_Print(file, "/* The engine may define the following macros:\n");
4301 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4302 for (i = 0;i < SHADERMODE_COUNT;i++)
4303 FS_Print(file, glslshadermodeinfo[i].pretext);
4304 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4305 FS_Print(file, shaderpermutationinfo[i].pretext);
4306 FS_Print(file, "*/\n");
4307 FS_Print(file, builtinshaderstring);
4309 Con_Printf("glsl/default.glsl written\n");
4312 Con_Printf("failed to write to glsl/default.glsl\n");
4315 file = FS_OpenRealFile("cg/default.cg", "w", false);
4318 FS_Print(file, "/* The engine may define the following macros:\n");
4319 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4320 for (i = 0;i < SHADERMODE_COUNT;i++)
4321 FS_Print(file, cgshadermodeinfo[i].pretext);
4322 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4323 FS_Print(file, shaderpermutationinfo[i].pretext);
4324 FS_Print(file, "*/\n");
4325 FS_Print(file, builtincgshaderstring);
4327 Con_Printf("cg/default.cg written\n");
4330 Con_Printf("failed to write to cg/default.cg\n");
4334 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4337 texturemode = GL_MODULATE;
4338 switch (vid.renderpath)
4340 case RENDERPATH_GL20:
4341 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))));
4342 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4343 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4345 case RENDERPATH_CGGL:
4348 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))));
4349 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4350 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4353 case RENDERPATH_GL13:
4354 R_Mesh_TexBind(0, first );
4355 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4356 R_Mesh_TexBind(1, second);
4358 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4360 case RENDERPATH_GL11:
4361 R_Mesh_TexBind(0, first );
4366 void R_SetupShader_DepthOrShadow(void)
4368 switch (vid.renderpath)
4370 case RENDERPATH_GL20:
4371 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4373 case RENDERPATH_CGGL:
4375 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4378 case RENDERPATH_GL13:
4379 R_Mesh_TexBind(0, 0);
4380 R_Mesh_TexBind(1, 0);
4382 case RENDERPATH_GL11:
4383 R_Mesh_TexBind(0, 0);
4388 void R_SetupShader_ShowDepth(void)
4390 switch (vid.renderpath)
4392 case RENDERPATH_GL20:
4393 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4395 case RENDERPATH_CGGL:
4397 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4400 case RENDERPATH_GL13:
4402 case RENDERPATH_GL11:
4407 extern qboolean r_shadow_usingdeferredprepass;
4408 extern cvar_t r_shadow_deferred_8bitrange;
4409 extern rtexture_t *r_shadow_attenuationgradienttexture;
4410 extern rtexture_t *r_shadow_attenuation2dtexture;
4411 extern rtexture_t *r_shadow_attenuation3dtexture;
4412 extern qboolean r_shadow_usingshadowmaprect;
4413 extern qboolean r_shadow_usingshadowmapcube;
4414 extern qboolean r_shadow_usingshadowmap2d;
4415 extern qboolean r_shadow_usingshadowmaportho;
4416 extern float r_shadow_shadowmap_texturescale[2];
4417 extern float r_shadow_shadowmap_parameters[4];
4418 extern qboolean r_shadow_shadowmapvsdct;
4419 extern qboolean r_shadow_shadowmapsampler;
4420 extern int r_shadow_shadowmappcf;
4421 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4422 extern rtexture_t *r_shadow_shadowmap2dtexture;
4423 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4424 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4425 extern matrix4x4_t r_shadow_shadowmapmatrix;
4426 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4427 extern int r_shadow_prepass_width;
4428 extern int r_shadow_prepass_height;
4429 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4430 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4431 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4432 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4433 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4435 // select a permutation of the lighting shader appropriate to this
4436 // combination of texture, entity, light source, and fogging, only use the
4437 // minimum features necessary to avoid wasting rendering time in the
4438 // fragment shader on features that are not being used
4439 unsigned int permutation = 0;
4440 unsigned int mode = 0;
4442 if (rsurfacepass == RSURFPASS_BACKGROUND)
4444 // distorted background
4445 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4446 mode = SHADERMODE_WATER;
4448 mode = SHADERMODE_REFRACTION;
4449 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4450 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4451 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4452 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4453 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4454 R_Mesh_ColorPointer(NULL, 0, 0);
4455 GL_AlphaTest(false);
4456 GL_BlendFunc(GL_ONE, GL_ZERO);
4458 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4460 if (r_glsl_offsetmapping.integer)
4462 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4463 if (r_glsl_offsetmapping_reliefmapping.integer)
4464 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4466 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4467 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4468 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4469 permutation |= SHADERPERMUTATION_ALPHAKILL;
4470 // normalmap (deferred prepass), may use alpha test on diffuse
4471 mode = SHADERMODE_DEFERREDGEOMETRY;
4472 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4473 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4474 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4475 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4476 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4477 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4478 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4479 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4480 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4482 R_Mesh_ColorPointer(NULL, 0, 0);
4483 GL_AlphaTest(false);
4484 GL_BlendFunc(GL_ONE, GL_ZERO);
4486 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4488 if (r_glsl_offsetmapping.integer)
4490 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4491 if (r_glsl_offsetmapping_reliefmapping.integer)
4492 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4494 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4495 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4497 mode = SHADERMODE_LIGHTSOURCE;
4498 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4499 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4500 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4501 permutation |= SHADERPERMUTATION_CUBEFILTER;
4502 if (diffusescale > 0)
4503 permutation |= SHADERPERMUTATION_DIFFUSE;
4504 if (specularscale > 0)
4506 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4507 if (r_shadow_glossexact.integer)
4508 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4510 if (r_refdef.fogenabled)
4511 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4512 if (rsurface.texture->colormapping)
4513 permutation |= SHADERPERMUTATION_COLORMAPPING;
4514 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4516 if (r_shadow_usingshadowmaprect)
4517 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4518 if (r_shadow_usingshadowmap2d)
4519 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4520 if (r_shadow_usingshadowmapcube)
4521 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4522 else if(r_shadow_shadowmapvsdct)
4523 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4525 if (r_shadow_shadowmapsampler)
4526 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4527 if (r_shadow_shadowmappcf > 1)
4528 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4529 else if (r_shadow_shadowmappcf)
4530 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4532 if (rsurface.texture->reflectmasktexture)
4533 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4534 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4535 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4537 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4538 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4539 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4543 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4544 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4545 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4547 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4548 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4549 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4551 R_Mesh_ColorPointer(NULL, 0, 0);
4552 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4553 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4555 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4557 if (r_glsl_offsetmapping.integer)
4559 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4560 if (r_glsl_offsetmapping_reliefmapping.integer)
4561 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4563 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4564 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4565 // unshaded geometry (fullbright or ambient model lighting)
4566 mode = SHADERMODE_FLATCOLOR;
4567 ambientscale = diffusescale = specularscale = 0;
4568 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4569 permutation |= SHADERPERMUTATION_GLOW;
4570 if (r_refdef.fogenabled)
4571 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4572 if (rsurface.texture->colormapping)
4573 permutation |= SHADERPERMUTATION_COLORMAPPING;
4574 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4576 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4577 if (r_shadow_usingshadowmaprect)
4578 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4579 if (r_shadow_usingshadowmap2d)
4580 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4582 if (r_shadow_shadowmapsampler)
4583 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4584 if (r_shadow_shadowmappcf > 1)
4585 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4586 else if (r_shadow_shadowmappcf)
4587 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4589 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4590 permutation |= SHADERPERMUTATION_REFLECTION;
4591 if (rsurface.texture->reflectmasktexture)
4592 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4593 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4594 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4596 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4597 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4598 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4602 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4603 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4604 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4606 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4607 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4608 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4610 R_Mesh_ColorPointer(NULL, 0, 0);
4611 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4612 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4614 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4616 if (r_glsl_offsetmapping.integer)
4618 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4619 if (r_glsl_offsetmapping_reliefmapping.integer)
4620 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4622 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4623 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4624 // directional model lighting
4625 mode = SHADERMODE_LIGHTDIRECTION;
4626 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4627 permutation |= SHADERPERMUTATION_GLOW;
4628 permutation |= SHADERPERMUTATION_DIFFUSE;
4629 if (specularscale > 0)
4631 permutation |= SHADERPERMUTATION_SPECULAR;
4632 if (r_shadow_glossexact.integer)
4633 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4635 if (r_refdef.fogenabled)
4636 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4637 if (rsurface.texture->colormapping)
4638 permutation |= SHADERPERMUTATION_COLORMAPPING;
4639 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4641 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4642 if (r_shadow_usingshadowmaprect)
4643 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4644 if (r_shadow_usingshadowmap2d)
4645 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4647 if (r_shadow_shadowmapsampler)
4648 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4649 if (r_shadow_shadowmappcf > 1)
4650 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4651 else if (r_shadow_shadowmappcf)
4652 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
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);
4678 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
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;
4688 // ambient model lighting
4689 mode = SHADERMODE_LIGHTDIRECTION;
4690 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4691 permutation |= SHADERPERMUTATION_GLOW;
4692 if (r_refdef.fogenabled)
4693 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4694 if (rsurface.texture->colormapping)
4695 permutation |= SHADERPERMUTATION_COLORMAPPING;
4696 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4698 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4699 if (r_shadow_usingshadowmaprect)
4700 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4701 if (r_shadow_usingshadowmap2d)
4702 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4704 if (r_shadow_shadowmapsampler)
4705 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4706 if (r_shadow_shadowmappcf > 1)
4707 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4708 else if (r_shadow_shadowmappcf)
4709 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4711 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4712 permutation |= SHADERPERMUTATION_REFLECTION;
4713 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4714 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4715 if (rsurface.texture->reflectmasktexture)
4716 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4717 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4718 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4720 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4721 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4722 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4726 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4727 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4728 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4730 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4731 R_Mesh_ColorPointer(NULL, 0, 0);
4732 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4733 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4737 if (r_glsl_offsetmapping.integer)
4739 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4740 if (r_glsl_offsetmapping_reliefmapping.integer)
4741 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4743 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4744 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4746 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4747 permutation |= SHADERPERMUTATION_GLOW;
4748 if (r_refdef.fogenabled)
4749 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4750 if (rsurface.texture->colormapping)
4751 permutation |= SHADERPERMUTATION_COLORMAPPING;
4752 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4754 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4755 if (r_shadow_usingshadowmaprect)
4756 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4757 if (r_shadow_usingshadowmap2d)
4758 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4760 if (r_shadow_shadowmapsampler)
4761 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4762 if (r_shadow_shadowmappcf > 1)
4763 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4764 else if (r_shadow_shadowmappcf)
4765 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4767 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4768 permutation |= SHADERPERMUTATION_REFLECTION;
4769 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4770 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4771 if (rsurface.texture->reflectmasktexture)
4772 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4773 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4775 // deluxemapping (light direction texture)
4776 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4777 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4779 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4780 permutation |= SHADERPERMUTATION_DIFFUSE;
4781 if (specularscale > 0)
4783 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4784 if (r_shadow_glossexact.integer)
4785 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4787 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4788 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4789 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4791 R_Mesh_ColorPointer(NULL, 0, 0);
4793 else if (r_glsl_deluxemapping.integer >= 2)
4795 // fake deluxemapping (uniform light direction in tangentspace)
4796 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4797 permutation |= SHADERPERMUTATION_DIFFUSE;
4798 if (specularscale > 0)
4800 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4801 if (r_shadow_glossexact.integer)
4802 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4804 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4805 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4806 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4808 R_Mesh_ColorPointer(NULL, 0, 0);
4810 else if (rsurface.uselightmaptexture)
4812 // ordinary lightmapping (q1bsp, q3bsp)
4813 mode = SHADERMODE_LIGHTMAP;
4814 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4815 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4816 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4818 R_Mesh_ColorPointer(NULL, 0, 0);
4822 // ordinary vertex coloring (q3bsp)
4823 mode = SHADERMODE_VERTEXCOLOR;
4824 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4825 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4827 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4828 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4830 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4831 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4832 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4836 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4837 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4838 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4840 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4841 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4843 switch(vid.renderpath)
4845 case RENDERPATH_GL20:
4846 R_SetupShader_SetPermutationGLSL(mode, permutation);
4847 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4848 if (mode == SHADERMODE_LIGHTSOURCE)
4850 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4851 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4852 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4853 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);
4854 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);
4855 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);
4857 // additive passes are only darkened by fog, not tinted
4858 if (r_glsl_permutation->loc_FogColor >= 0)
4859 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4860 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4864 if (mode == SHADERMODE_FLATCOLOR)
4866 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4868 else if (mode == SHADERMODE_LIGHTDIRECTION)
4870 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]);
4871 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]);
4872 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);
4873 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);
4874 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);
4875 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]);
4876 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]);
4880 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]);
4881 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]);
4882 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);
4883 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);
4884 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);
4886 // additive passes are only darkened by fog, not tinted
4887 if (r_glsl_permutation->loc_FogColor >= 0)
4889 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4890 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4892 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4894 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);
4895 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]);
4896 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]);
4897 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4898 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4899 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4900 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4901 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4903 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4904 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4905 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
4906 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]);
4907 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]);
4909 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4910 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4911 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4912 if (r_glsl_permutation->loc_Color_Pants >= 0)
4914 if (rsurface.texture->pantstexture)
4915 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4917 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4919 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4921 if (rsurface.texture->shirttexture)
4922 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4924 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4926 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]);
4927 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4928 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4929 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4930 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4931 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]);
4932 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4934 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
4935 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
4936 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
4937 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
4938 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
4939 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
4940 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
4941 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
4942 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
4943 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
4944 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
4945 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
4946 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
4947 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
4948 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
4949 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
4950 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
4951 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap );
4952 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
4953 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white );
4954 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white );
4955 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
4956 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
4957 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
4958 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
4959 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
4961 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
4962 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture );
4963 if (rsurface.rtlight)
4965 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
4966 if (r_shadow_usingshadowmapcube)
4967 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4968 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
4973 case RENDERPATH_CGGL:
4975 R_SetupShader_SetPermutationCG(mode, permutation);
4976 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
4977 if (mode == SHADERMODE_LIGHTSOURCE)
4979 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4980 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4984 if (mode == SHADERMODE_LIGHTDIRECTION)
4986 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
4989 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4990 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4991 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
4992 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4993 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
4996 if (mode == SHADERMODE_LIGHTSOURCE)
4998 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4999 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5000 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
5001 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
5002 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
5004 // additive passes are only darkened by fog, not tinted
5005 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5006 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5010 if (mode == SHADERMODE_FLATCOLOR)
5012 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5014 else if (mode == SHADERMODE_LIGHTDIRECTION)
5016 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
5017 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
5018 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
5019 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
5020 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
5021 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
5022 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
5026 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
5027 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
5028 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
5029 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
5030 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
5032 // additive passes are only darkened by fog, not tinted
5033 if (r_cg_permutation->fp_FogColor)
5035 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5036 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5038 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5041 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
5042 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
5043 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
5044 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5045 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5046 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5047 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5048 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5050 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
5051 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
5052 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5053 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5054 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5055 if (r_cg_permutation->fp_Color_Pants)
5057 if (rsurface.texture->pantstexture)
5058 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5060 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5063 if (r_cg_permutation->fp_Color_Shirt)
5065 if (rsurface.texture->shirttexture)
5066 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5068 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5071 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
5072 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5073 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5074 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5075 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5076 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
5077 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5079 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
5080 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
5081 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
5082 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
5083 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
5084 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
5085 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
5086 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
5087 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
5088 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
5089 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
5090 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
5091 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
5092 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
5093 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
5094 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
5095 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
5096 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
5097 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5098 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , r_texture_white );CHECKCGERROR
5099 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , r_texture_white );CHECKCGERROR
5100 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5101 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5102 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
5103 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
5104 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5106 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5107 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5108 if (rsurface.rtlight)
5110 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5111 if (r_shadow_usingshadowmapcube)
5112 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5113 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5120 case RENDERPATH_GL13:
5121 case RENDERPATH_GL11:
5126 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5128 // select a permutation of the lighting shader appropriate to this
5129 // combination of texture, entity, light source, and fogging, only use the
5130 // minimum features necessary to avoid wasting rendering time in the
5131 // fragment shader on features that are not being used
5132 unsigned int permutation = 0;
5133 unsigned int mode = 0;
5134 const float *lightcolorbase = rtlight->currentcolor;
5135 float ambientscale = rtlight->ambientscale;
5136 float diffusescale = rtlight->diffusescale;
5137 float specularscale = rtlight->specularscale;
5138 // this is the location of the light in view space
5139 vec3_t viewlightorigin;
5140 // this transforms from view space (camera) to light space (cubemap)
5141 matrix4x4_t viewtolight;
5142 matrix4x4_t lighttoview;
5143 float viewtolight16f[16];
5144 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5146 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5147 if (rtlight->currentcubemap != r_texture_whitecube)
5148 permutation |= SHADERPERMUTATION_CUBEFILTER;
5149 if (diffusescale > 0)
5150 permutation |= SHADERPERMUTATION_DIFFUSE;
5151 if (specularscale > 0)
5153 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5154 if (r_shadow_glossexact.integer)
5155 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5157 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5159 if (r_shadow_usingshadowmaprect)
5160 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5161 if (r_shadow_usingshadowmap2d)
5162 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5163 if (r_shadow_usingshadowmapcube)
5164 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5165 else if(r_shadow_shadowmapvsdct)
5166 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5168 if (r_shadow_shadowmapsampler)
5169 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5170 if (r_shadow_shadowmappcf > 1)
5171 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5172 else if (r_shadow_shadowmappcf)
5173 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5175 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5176 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5177 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5178 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5179 switch(vid.renderpath)
5181 case RENDERPATH_GL20:
5182 R_SetupShader_SetPermutationGLSL(mode, permutation);
5183 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5184 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5185 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);
5186 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);
5187 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);
5188 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]);
5189 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]);
5190 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));
5191 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]);
5192 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5194 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5195 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5196 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5197 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5198 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
5199 if (r_shadow_usingshadowmapcube)
5200 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5201 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5202 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5204 case RENDERPATH_CGGL:
5206 R_SetupShader_SetPermutationCG(mode, permutation);
5207 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5208 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5209 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
5210 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
5211 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
5212 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
5213 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
5214 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
5215 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
5216 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5218 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5219 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5220 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5221 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5222 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5223 if (r_shadow_usingshadowmapcube)
5224 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5225 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5226 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5229 case RENDERPATH_GL13:
5230 case RENDERPATH_GL11:
5235 #define SKINFRAME_HASH 1024
5239 int loadsequence; // incremented each level change
5240 memexpandablearray_t array;
5241 skinframe_t *hash[SKINFRAME_HASH];
5244 r_skinframe_t r_skinframe;
5246 void R_SkinFrame_PrepareForPurge(void)
5248 r_skinframe.loadsequence++;
5249 // wrap it without hitting zero
5250 if (r_skinframe.loadsequence >= 200)
5251 r_skinframe.loadsequence = 1;
5254 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5258 // mark the skinframe as used for the purging code
5259 skinframe->loadsequence = r_skinframe.loadsequence;
5262 void R_SkinFrame_Purge(void)
5266 for (i = 0;i < SKINFRAME_HASH;i++)
5268 for (s = r_skinframe.hash[i];s;s = s->next)
5270 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5272 if (s->merged == s->base)
5274 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5275 R_PurgeTexture(s->stain );s->stain = NULL;
5276 R_PurgeTexture(s->merged);s->merged = NULL;
5277 R_PurgeTexture(s->base );s->base = NULL;
5278 R_PurgeTexture(s->pants );s->pants = NULL;
5279 R_PurgeTexture(s->shirt );s->shirt = NULL;
5280 R_PurgeTexture(s->nmap );s->nmap = NULL;
5281 R_PurgeTexture(s->gloss );s->gloss = NULL;
5282 R_PurgeTexture(s->glow );s->glow = NULL;
5283 R_PurgeTexture(s->fog );s->fog = NULL;
5284 R_PurgeTexture(s->reflect);s->reflect = NULL;
5285 s->loadsequence = 0;
5291 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5293 char basename[MAX_QPATH];
5295 Image_StripImageExtension(name, basename, sizeof(basename));
5297 if( last == NULL ) {
5299 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5300 item = r_skinframe.hash[hashindex];
5305 // linearly search through the hash bucket
5306 for( ; item ; item = item->next ) {
5307 if( !strcmp( item->basename, basename ) ) {
5314 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5318 char basename[MAX_QPATH];
5320 Image_StripImageExtension(name, basename, sizeof(basename));
5322 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5323 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5324 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5328 rtexture_t *dyntexture;
5329 // check whether its a dynamic texture
5330 dyntexture = CL_GetDynTexture( basename );
5331 if (!add && !dyntexture)
5333 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5334 memset(item, 0, sizeof(*item));
5335 strlcpy(item->basename, basename, sizeof(item->basename));
5336 item->base = dyntexture; // either NULL or dyntexture handle
5337 item->textureflags = textureflags;
5338 item->comparewidth = comparewidth;
5339 item->compareheight = compareheight;
5340 item->comparecrc = comparecrc;
5341 item->next = r_skinframe.hash[hashindex];
5342 r_skinframe.hash[hashindex] = item;
5344 else if( item->base == NULL )
5346 rtexture_t *dyntexture;
5347 // check whether its a dynamic texture
5348 // 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]
5349 dyntexture = CL_GetDynTexture( basename );
5350 item->base = dyntexture; // either NULL or dyntexture handle
5353 R_SkinFrame_MarkUsed(item);
5357 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5359 unsigned long long avgcolor[5], wsum; \
5367 for(pix = 0; pix < cnt; ++pix) \
5370 for(comp = 0; comp < 3; ++comp) \
5372 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5375 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5377 for(comp = 0; comp < 3; ++comp) \
5378 avgcolor[comp] += getpixel * w; \
5381 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5382 avgcolor[4] += getpixel; \
5384 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5386 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5387 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5388 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5389 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5392 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5395 unsigned char *pixels;
5396 unsigned char *bumppixels;
5397 unsigned char *basepixels = NULL;
5398 int basepixels_width = 0;
5399 int basepixels_height = 0;
5400 skinframe_t *skinframe;
5401 rtexture_t *ddsbase = NULL;
5402 qboolean ddshasalpha = false;
5403 float ddsavgcolor[4];
5404 char basename[MAX_QPATH];
5406 if (cls.state == ca_dedicated)
5409 // return an existing skinframe if already loaded
5410 // if loading of the first image fails, don't make a new skinframe as it
5411 // would cause all future lookups of this to be missing
5412 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5413 if (skinframe && skinframe->base)
5416 Image_StripImageExtension(name, basename, sizeof(basename));
5418 // check for DDS texture file first
5419 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5421 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5422 if (basepixels == NULL)
5426 if (developer_loading.integer)
5427 Con_Printf("loading skin \"%s\"\n", name);
5429 // we've got some pixels to store, so really allocate this new texture now
5431 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5432 skinframe->stain = NULL;
5433 skinframe->merged = NULL;
5434 skinframe->base = NULL;
5435 skinframe->pants = NULL;
5436 skinframe->shirt = NULL;
5437 skinframe->nmap = NULL;
5438 skinframe->gloss = NULL;
5439 skinframe->glow = NULL;
5440 skinframe->fog = NULL;
5441 skinframe->reflect = NULL;
5442 skinframe->hasalpha = false;
5446 skinframe->base = ddsbase;
5447 skinframe->hasalpha = ddshasalpha;
5448 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5449 if (r_loadfog && skinframe->hasalpha)
5450 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5451 //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]);
5455 basepixels_width = image_width;
5456 basepixels_height = image_height;
5457 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);
5458 if (textureflags & TEXF_ALPHA)
5460 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5462 if (basepixels[j] < 255)
5464 skinframe->hasalpha = true;
5468 if (r_loadfog && skinframe->hasalpha)
5470 // has transparent pixels
5471 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5472 for (j = 0;j < image_width * image_height * 4;j += 4)
5477 pixels[j+3] = basepixels[j+3];
5479 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);
5483 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5484 //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]);
5485 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5486 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5487 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5488 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5493 if (r_loadnormalmap)
5494 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5495 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5497 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5498 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5499 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5500 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5503 // _norm is the name used by tenebrae and has been adopted as standard
5504 if (r_loadnormalmap && skinframe->nmap == NULL)
5506 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5508 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);
5512 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5514 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5515 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5516 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);
5518 Mem_Free(bumppixels);
5520 else if (r_shadow_bumpscale_basetexture.value > 0)
5522 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5523 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5524 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);
5527 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5528 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5531 // _luma is supported only for tenebrae compatibility
5532 // _glow is the preferred name
5533 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))))
5535 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);
5536 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5537 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5538 Mem_Free(pixels);pixels = NULL;
5541 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5543 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);
5544 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5545 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5550 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5552 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);
5553 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5554 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5559 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5561 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);
5562 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5563 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5568 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5570 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);
5571 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5572 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5578 Mem_Free(basepixels);
5583 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5584 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5587 unsigned char *temp1, *temp2;
5588 skinframe_t *skinframe;
5590 if (cls.state == ca_dedicated)
5593 // if already loaded just return it, otherwise make a new skinframe
5594 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5595 if (skinframe && skinframe->base)
5598 skinframe->stain = NULL;
5599 skinframe->merged = NULL;
5600 skinframe->base = NULL;
5601 skinframe->pants = NULL;
5602 skinframe->shirt = NULL;
5603 skinframe->nmap = NULL;
5604 skinframe->gloss = NULL;
5605 skinframe->glow = NULL;
5606 skinframe->fog = NULL;
5607 skinframe->reflect = NULL;
5608 skinframe->hasalpha = false;
5610 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5614 if (developer_loading.integer)
5615 Con_Printf("loading 32bit skin \"%s\"\n", name);
5617 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5619 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5620 temp2 = temp1 + width * height * 4;
5621 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5622 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5625 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5626 if (textureflags & TEXF_ALPHA)
5628 for (i = 3;i < width * height * 4;i += 4)
5630 if (skindata[i] < 255)
5632 skinframe->hasalpha = true;
5636 if (r_loadfog && skinframe->hasalpha)
5638 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5639 memcpy(fogpixels, skindata, width * height * 4);
5640 for (i = 0;i < width * height * 4;i += 4)
5641 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5642 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5643 Mem_Free(fogpixels);
5647 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5648 //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]);
5653 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5657 skinframe_t *skinframe;
5659 if (cls.state == ca_dedicated)
5662 // if already loaded just return it, otherwise make a new skinframe
5663 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5664 if (skinframe && skinframe->base)
5667 skinframe->stain = NULL;
5668 skinframe->merged = NULL;
5669 skinframe->base = NULL;
5670 skinframe->pants = NULL;
5671 skinframe->shirt = NULL;
5672 skinframe->nmap = NULL;
5673 skinframe->gloss = NULL;
5674 skinframe->glow = NULL;
5675 skinframe->fog = NULL;
5676 skinframe->reflect = NULL;
5677 skinframe->hasalpha = false;
5679 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5683 if (developer_loading.integer)
5684 Con_Printf("loading quake skin \"%s\"\n", name);
5686 // 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)
5687 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5688 memcpy(skinframe->qpixels, skindata, width*height);
5689 skinframe->qwidth = width;
5690 skinframe->qheight = height;
5693 for (i = 0;i < width * height;i++)
5694 featuresmask |= palette_featureflags[skindata[i]];
5696 skinframe->hasalpha = false;
5697 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5698 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5699 skinframe->qgeneratemerged = true;
5700 skinframe->qgeneratebase = skinframe->qhascolormapping;
5701 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5703 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5704 //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]);
5709 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5713 unsigned char *skindata;
5715 if (!skinframe->qpixels)
5718 if (!skinframe->qhascolormapping)
5719 colormapped = false;
5723 if (!skinframe->qgeneratebase)
5728 if (!skinframe->qgeneratemerged)
5732 width = skinframe->qwidth;
5733 height = skinframe->qheight;
5734 skindata = skinframe->qpixels;
5736 if (skinframe->qgeneratenmap)
5738 unsigned char *temp1, *temp2;
5739 skinframe->qgeneratenmap = false;
5740 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5741 temp2 = temp1 + width * height * 4;
5742 // use either a custom palette or the quake palette
5743 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5744 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5745 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5749 if (skinframe->qgenerateglow)
5751 skinframe->qgenerateglow = false;
5752 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5757 skinframe->qgeneratebase = false;
5758 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);
5759 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5760 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5764 skinframe->qgeneratemerged = false;
5765 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5768 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5770 Mem_Free(skinframe->qpixels);
5771 skinframe->qpixels = NULL;
5775 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)
5778 skinframe_t *skinframe;
5780 if (cls.state == ca_dedicated)
5783 // if already loaded just return it, otherwise make a new skinframe
5784 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5785 if (skinframe && skinframe->base)
5788 skinframe->stain = NULL;
5789 skinframe->merged = NULL;
5790 skinframe->base = NULL;
5791 skinframe->pants = NULL;
5792 skinframe->shirt = NULL;
5793 skinframe->nmap = NULL;
5794 skinframe->gloss = NULL;
5795 skinframe->glow = NULL;
5796 skinframe->fog = NULL;
5797 skinframe->reflect = NULL;
5798 skinframe->hasalpha = false;
5800 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5804 if (developer_loading.integer)
5805 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5807 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5808 if (textureflags & TEXF_ALPHA)
5810 for (i = 0;i < width * height;i++)
5812 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5814 skinframe->hasalpha = true;
5818 if (r_loadfog && skinframe->hasalpha)
5819 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5822 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5823 //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]);
5828 skinframe_t *R_SkinFrame_LoadMissing(void)
5830 skinframe_t *skinframe;
5832 if (cls.state == ca_dedicated)
5835 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5836 skinframe->stain = NULL;
5837 skinframe->merged = NULL;
5838 skinframe->base = NULL;
5839 skinframe->pants = NULL;
5840 skinframe->shirt = NULL;
5841 skinframe->nmap = NULL;
5842 skinframe->gloss = NULL;
5843 skinframe->glow = NULL;
5844 skinframe->fog = NULL;
5845 skinframe->reflect = NULL;
5846 skinframe->hasalpha = false;
5848 skinframe->avgcolor[0] = rand() / RAND_MAX;
5849 skinframe->avgcolor[1] = rand() / RAND_MAX;
5850 skinframe->avgcolor[2] = rand() / RAND_MAX;
5851 skinframe->avgcolor[3] = 1;
5856 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5857 typedef struct suffixinfo_s
5860 qboolean flipx, flipy, flipdiagonal;
5863 static suffixinfo_t suffix[3][6] =
5866 {"px", false, false, false},
5867 {"nx", false, false, false},
5868 {"py", false, false, false},
5869 {"ny", false, false, false},
5870 {"pz", false, false, false},
5871 {"nz", false, false, false}
5874 {"posx", false, false, false},
5875 {"negx", false, false, false},
5876 {"posy", false, false, false},
5877 {"negy", false, false, false},
5878 {"posz", false, false, false},
5879 {"negz", false, false, false}
5882 {"rt", true, false, true},
5883 {"lf", false, true, true},
5884 {"ft", true, true, false},
5885 {"bk", false, false, false},
5886 {"up", true, false, true},
5887 {"dn", true, false, true}
5891 static int componentorder[4] = {0, 1, 2, 3};
5893 rtexture_t *R_LoadCubemap(const char *basename)
5895 int i, j, cubemapsize;
5896 unsigned char *cubemappixels, *image_buffer;
5897 rtexture_t *cubemaptexture;
5899 // must start 0 so the first loadimagepixels has no requested width/height
5901 cubemappixels = NULL;
5902 cubemaptexture = NULL;
5903 // keep trying different suffix groups (posx, px, rt) until one loads
5904 for (j = 0;j < 3 && !cubemappixels;j++)
5906 // load the 6 images in the suffix group
5907 for (i = 0;i < 6;i++)
5909 // generate an image name based on the base and and suffix
5910 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5912 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
5914 // an image loaded, make sure width and height are equal
5915 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
5917 // if this is the first image to load successfully, allocate the cubemap memory
5918 if (!cubemappixels && image_width >= 1)
5920 cubemapsize = image_width;
5921 // note this clears to black, so unavailable sides are black
5922 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
5924 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
5926 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);
5929 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
5931 Mem_Free(image_buffer);
5935 // if a cubemap loaded, upload it
5938 if (developer_loading.integer)
5939 Con_Printf("loading cubemap \"%s\"\n", basename);
5941 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
5942 Mem_Free(cubemappixels);
5946 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
5947 if (developer_loading.integer)
5949 Con_Printf("(tried tried images ");
5950 for (j = 0;j < 3;j++)
5951 for (i = 0;i < 6;i++)
5952 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
5953 Con_Print(" and was unable to find any of them).\n");
5956 return cubemaptexture;
5959 rtexture_t *R_GetCubemap(const char *basename)
5962 for (i = 0;i < r_texture_numcubemaps;i++)
5963 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
5964 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
5965 if (i >= MAX_CUBEMAPS)
5966 return r_texture_whitecube;
5967 r_texture_numcubemaps++;
5968 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
5969 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
5970 return r_texture_cubemaps[i].texture;
5973 void R_FreeCubemaps(void)
5976 for (i = 0;i < r_texture_numcubemaps;i++)
5978 if (developer_loading.integer)
5979 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
5980 if (r_texture_cubemaps[i].texture)
5981 R_FreeTexture(r_texture_cubemaps[i].texture);
5983 r_texture_numcubemaps = 0;
5986 void R_Main_FreeViewCache(void)
5988 if (r_refdef.viewcache.entityvisible)
5989 Mem_Free(r_refdef.viewcache.entityvisible);
5990 if (r_refdef.viewcache.world_pvsbits)
5991 Mem_Free(r_refdef.viewcache.world_pvsbits);
5992 if (r_refdef.viewcache.world_leafvisible)
5993 Mem_Free(r_refdef.viewcache.world_leafvisible);
5994 if (r_refdef.viewcache.world_surfacevisible)
5995 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5996 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5999 void R_Main_ResizeViewCache(void)
6001 int numentities = r_refdef.scene.numentities;
6002 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6003 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6004 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6005 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6006 if (r_refdef.viewcache.maxentities < numentities)
6008 r_refdef.viewcache.maxentities = numentities;
6009 if (r_refdef.viewcache.entityvisible)
6010 Mem_Free(r_refdef.viewcache.entityvisible);
6011 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6013 if (r_refdef.viewcache.world_numclusters != numclusters)
6015 r_refdef.viewcache.world_numclusters = numclusters;
6016 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6017 if (r_refdef.viewcache.world_pvsbits)
6018 Mem_Free(r_refdef.viewcache.world_pvsbits);
6019 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6021 if (r_refdef.viewcache.world_numleafs != numleafs)
6023 r_refdef.viewcache.world_numleafs = numleafs;
6024 if (r_refdef.viewcache.world_leafvisible)
6025 Mem_Free(r_refdef.viewcache.world_leafvisible);
6026 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6028 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6030 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6031 if (r_refdef.viewcache.world_surfacevisible)
6032 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6033 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6037 extern rtexture_t *loadingscreentexture;
6038 void gl_main_start(void)
6040 loadingscreentexture = NULL;
6041 r_texture_blanknormalmap = NULL;
6042 r_texture_white = NULL;
6043 r_texture_grey128 = NULL;
6044 r_texture_black = NULL;
6045 r_texture_whitecube = NULL;
6046 r_texture_normalizationcube = NULL;
6047 r_texture_fogattenuation = NULL;
6048 r_texture_gammaramps = NULL;
6049 r_texture_numcubemaps = 0;
6051 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6052 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6054 switch(vid.renderpath)
6056 case RENDERPATH_GL20:
6057 case RENDERPATH_CGGL:
6058 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6059 Cvar_SetValueQuick(&gl_combine, 1);
6060 Cvar_SetValueQuick(&r_glsl, 1);
6061 r_loadnormalmap = true;
6065 case RENDERPATH_GL13:
6066 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6067 Cvar_SetValueQuick(&gl_combine, 1);
6068 Cvar_SetValueQuick(&r_glsl, 0);
6069 r_loadnormalmap = false;
6070 r_loadgloss = false;
6073 case RENDERPATH_GL11:
6074 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6075 Cvar_SetValueQuick(&gl_combine, 0);
6076 Cvar_SetValueQuick(&r_glsl, 0);
6077 r_loadnormalmap = false;
6078 r_loadgloss = false;
6084 R_FrameData_Reset();
6088 memset(r_queries, 0, sizeof(r_queries));
6090 r_qwskincache = NULL;
6091 r_qwskincache_size = 0;
6093 // set up r_skinframe loading system for textures
6094 memset(&r_skinframe, 0, sizeof(r_skinframe));
6095 r_skinframe.loadsequence = 1;
6096 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6098 r_main_texturepool = R_AllocTexturePool();
6099 R_BuildBlankTextures();
6101 if (vid.support.arb_texture_cube_map)
6104 R_BuildNormalizationCube();
6106 r_texture_fogattenuation = NULL;
6107 r_texture_gammaramps = NULL;
6108 //r_texture_fogintensity = NULL;
6109 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6110 memset(&r_waterstate, 0, sizeof(r_waterstate));
6111 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6112 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6113 glslshaderstring = NULL;
6115 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6116 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6117 cgshaderstring = NULL;
6119 memset(&r_svbsp, 0, sizeof (r_svbsp));
6121 r_refdef.fogmasktable_density = 0;
6124 void gl_main_shutdown(void)
6127 R_FrameData_Reset();
6129 R_Main_FreeViewCache();
6132 qglDeleteQueriesARB(r_maxqueries, r_queries);
6136 memset(r_queries, 0, sizeof(r_queries));
6138 r_qwskincache = NULL;
6139 r_qwskincache_size = 0;
6141 // clear out the r_skinframe state
6142 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6143 memset(&r_skinframe, 0, sizeof(r_skinframe));
6146 Mem_Free(r_svbsp.nodes);
6147 memset(&r_svbsp, 0, sizeof (r_svbsp));
6148 R_FreeTexturePool(&r_main_texturepool);
6149 loadingscreentexture = NULL;
6150 r_texture_blanknormalmap = NULL;
6151 r_texture_white = NULL;
6152 r_texture_grey128 = NULL;
6153 r_texture_black = NULL;
6154 r_texture_whitecube = NULL;
6155 r_texture_normalizationcube = NULL;
6156 r_texture_fogattenuation = NULL;
6157 r_texture_gammaramps = NULL;
6158 r_texture_numcubemaps = 0;
6159 //r_texture_fogintensity = NULL;
6160 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6161 memset(&r_waterstate, 0, sizeof(r_waterstate));
6165 extern void CL_ParseEntityLump(char *entitystring);
6166 void gl_main_newmap(void)
6168 // FIXME: move this code to client
6170 char *entities, entname[MAX_QPATH];
6172 Mem_Free(r_qwskincache);
6173 r_qwskincache = NULL;
6174 r_qwskincache_size = 0;
6177 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6178 l = (int)strlen(entname) - 4;
6179 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6181 memcpy(entname + l, ".ent", 5);
6182 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6184 CL_ParseEntityLump(entities);
6189 if (cl.worldmodel->brush.entities)
6190 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6192 R_Main_FreeViewCache();
6194 R_FrameData_Reset();
6197 void GL_Main_Init(void)
6199 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6201 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6202 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6203 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6204 if (gamemode == GAME_NEHAHRA)
6206 Cvar_RegisterVariable (&gl_fogenable);
6207 Cvar_RegisterVariable (&gl_fogdensity);
6208 Cvar_RegisterVariable (&gl_fogred);
6209 Cvar_RegisterVariable (&gl_foggreen);
6210 Cvar_RegisterVariable (&gl_fogblue);
6211 Cvar_RegisterVariable (&gl_fogstart);
6212 Cvar_RegisterVariable (&gl_fogend);
6213 Cvar_RegisterVariable (&gl_skyclip);
6215 Cvar_RegisterVariable(&r_motionblur);
6216 Cvar_RegisterVariable(&r_motionblur_maxblur);
6217 Cvar_RegisterVariable(&r_motionblur_bmin);
6218 Cvar_RegisterVariable(&r_motionblur_vmin);
6219 Cvar_RegisterVariable(&r_motionblur_vmax);
6220 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6221 Cvar_RegisterVariable(&r_motionblur_randomize);
6222 Cvar_RegisterVariable(&r_damageblur);
6223 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6224 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6225 Cvar_RegisterVariable(&r_equalize_entities_by);
6226 Cvar_RegisterVariable(&r_equalize_entities_to);
6227 Cvar_RegisterVariable(&r_depthfirst);
6228 Cvar_RegisterVariable(&r_useinfinitefarclip);
6229 Cvar_RegisterVariable(&r_farclip_base);
6230 Cvar_RegisterVariable(&r_farclip_world);
6231 Cvar_RegisterVariable(&r_nearclip);
6232 Cvar_RegisterVariable(&r_showbboxes);
6233 Cvar_RegisterVariable(&r_showsurfaces);
6234 Cvar_RegisterVariable(&r_showtris);
6235 Cvar_RegisterVariable(&r_shownormals);
6236 Cvar_RegisterVariable(&r_showlighting);
6237 Cvar_RegisterVariable(&r_showshadowvolumes);
6238 Cvar_RegisterVariable(&r_showcollisionbrushes);
6239 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6240 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6241 Cvar_RegisterVariable(&r_showdisabledepthtest);
6242 Cvar_RegisterVariable(&r_drawportals);
6243 Cvar_RegisterVariable(&r_drawentities);
6244 Cvar_RegisterVariable(&r_cullentities_trace);
6245 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6246 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6247 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6248 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6249 Cvar_RegisterVariable(&r_drawviewmodel);
6250 Cvar_RegisterVariable(&r_speeds);
6251 Cvar_RegisterVariable(&r_fullbrights);
6252 Cvar_RegisterVariable(&r_wateralpha);
6253 Cvar_RegisterVariable(&r_dynamic);
6254 Cvar_RegisterVariable(&r_fullbright);
6255 Cvar_RegisterVariable(&r_shadows);
6256 Cvar_RegisterVariable(&r_shadows_darken);
6257 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6258 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6259 Cvar_RegisterVariable(&r_shadows_throwdistance);
6260 Cvar_RegisterVariable(&r_shadows_throwdirection);
6261 Cvar_RegisterVariable(&r_shadows_focus);
6262 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6263 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6264 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6265 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6266 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6267 Cvar_RegisterVariable(&r_fog_exp2);
6268 Cvar_RegisterVariable(&r_drawfog);
6269 Cvar_RegisterVariable(&r_transparentdepthmasking);
6270 Cvar_RegisterVariable(&r_texture_dds_load);
6271 Cvar_RegisterVariable(&r_texture_dds_save);
6272 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6273 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6274 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6275 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6276 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6277 Cvar_RegisterVariable(&r_textureunits);
6278 Cvar_RegisterVariable(&gl_combine);
6279 Cvar_RegisterVariable(&r_glsl);
6280 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6281 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6282 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6283 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6284 Cvar_RegisterVariable(&r_glsl_postprocess);
6285 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6286 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6287 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6288 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6289 Cvar_RegisterVariable(&r_water);
6290 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6291 Cvar_RegisterVariable(&r_water_clippingplanebias);
6292 Cvar_RegisterVariable(&r_water_refractdistort);
6293 Cvar_RegisterVariable(&r_water_reflectdistort);
6294 Cvar_RegisterVariable(&r_lerpsprites);
6295 Cvar_RegisterVariable(&r_lerpmodels);
6296 Cvar_RegisterVariable(&r_lerplightstyles);
6297 Cvar_RegisterVariable(&r_waterscroll);
6298 Cvar_RegisterVariable(&r_bloom);
6299 Cvar_RegisterVariable(&r_bloom_colorscale);
6300 Cvar_RegisterVariable(&r_bloom_brighten);
6301 Cvar_RegisterVariable(&r_bloom_blur);
6302 Cvar_RegisterVariable(&r_bloom_resolution);
6303 Cvar_RegisterVariable(&r_bloom_colorexponent);
6304 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6305 Cvar_RegisterVariable(&r_hdr);
6306 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6307 Cvar_RegisterVariable(&r_hdr_glowintensity);
6308 Cvar_RegisterVariable(&r_hdr_range);
6309 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6310 Cvar_RegisterVariable(&developer_texturelogging);
6311 Cvar_RegisterVariable(&gl_lightmaps);
6312 Cvar_RegisterVariable(&r_test);
6313 Cvar_RegisterVariable(&r_batchmode);
6314 Cvar_RegisterVariable(&r_glsl_saturation);
6315 Cvar_RegisterVariable(&r_framedatasize);
6316 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6317 Cvar_SetValue("r_fullbrights", 0);
6318 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6320 Cvar_RegisterVariable(&r_track_sprites);
6321 Cvar_RegisterVariable(&r_track_sprites_flags);
6322 Cvar_RegisterVariable(&r_track_sprites_scalew);
6323 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6324 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6325 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6328 extern void R_Textures_Init(void);
6329 extern void GL_Draw_Init(void);
6330 extern void GL_Main_Init(void);
6331 extern void R_Shadow_Init(void);
6332 extern void R_Sky_Init(void);
6333 extern void GL_Surf_Init(void);
6334 extern void R_Particles_Init(void);
6335 extern void R_Explosion_Init(void);
6336 extern void gl_backend_init(void);
6337 extern void Sbar_Init(void);
6338 extern void R_LightningBeams_Init(void);
6339 extern void Mod_RenderInit(void);
6340 extern void Font_Init(void);
6342 void Render_Init(void)
6355 R_LightningBeams_Init();
6364 extern char *ENGINE_EXTENSIONS;
6367 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6368 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6369 gl_version = (const char *)qglGetString(GL_VERSION);
6370 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6374 if (!gl_platformextensions)
6375 gl_platformextensions = "";
6377 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6378 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6379 Con_Printf("GL_VERSION: %s\n", gl_version);
6380 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6381 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6383 VID_CheckExtensions();
6385 // LordHavoc: report supported extensions
6386 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6388 // clear to black (loading plaque will be seen over this)
6390 qglClearColor(0,0,0,1);CHECKGLERROR
6391 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6394 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6398 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6400 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6403 p = r_refdef.view.frustum + i;
6408 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6412 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6416 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6420 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6424 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6428 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6432 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6436 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6444 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6448 for (i = 0;i < numplanes;i++)
6455 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6459 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6463 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6467 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6471 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6475 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6479 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6483 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6491 //==================================================================================
6493 // LordHavoc: this stores temporary data used within the same frame
6495 qboolean r_framedata_failed;
6496 static size_t r_framedata_size;
6497 static size_t r_framedata_current;
6498 static void *r_framedata_base;
6500 void R_FrameData_Reset(void)
6502 if (r_framedata_base)
6503 Mem_Free(r_framedata_base);
6504 r_framedata_base = NULL;
6505 r_framedata_size = 0;
6506 r_framedata_current = 0;
6507 r_framedata_failed = false;
6510 void R_FrameData_NewFrame(void)
6513 if (r_framedata_failed)
6514 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6515 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6516 wantedsize = bound(65536, wantedsize, 128*1024*1024);
6517 if (r_framedata_size != wantedsize)
6519 r_framedata_size = wantedsize;
6520 if (r_framedata_base)
6521 Mem_Free(r_framedata_base);
6522 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6524 r_framedata_current = 0;
6525 r_framedata_failed = false;
6528 void *R_FrameData_Alloc(size_t size)
6532 // align to 16 byte boundary
6533 size = (size + 15) & ~15;
6534 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6535 r_framedata_current += size;
6538 if (r_framedata_current > r_framedata_size)
6539 r_framedata_failed = true;
6541 // return NULL on everything after a failure
6542 if (r_framedata_failed)
6548 void *R_FrameData_Store(size_t size, void *data)
6550 void *d = R_FrameData_Alloc(size);
6552 memcpy(d, data, size);
6556 //==================================================================================
6558 // LordHavoc: animcache originally written by Echon, rewritten since then
6561 * Animation cache prevents re-generating mesh data for an animated model
6562 * multiple times in one frame for lighting, shadowing, reflections, etc.
6565 void R_AnimCache_Free(void)
6569 void R_AnimCache_ClearCache(void)
6572 entity_render_t *ent;
6574 for (i = 0;i < r_refdef.scene.numentities;i++)
6576 ent = r_refdef.scene.entities[i];
6577 ent->animcache_vertex3f = NULL;
6578 ent->animcache_normal3f = NULL;
6579 ent->animcache_svector3f = NULL;
6580 ent->animcache_tvector3f = NULL;
6584 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6586 dp_model_t *model = ent->model;
6588 // see if it's already cached this frame
6589 if (ent->animcache_vertex3f)
6591 // add normals/tangents if needed
6592 if (wantnormals || wanttangents)
6594 if (ent->animcache_normal3f)
6595 wantnormals = false;
6596 if (ent->animcache_svector3f)
6597 wanttangents = false;
6598 if (wantnormals || wanttangents)
6600 numvertices = model->surfmesh.num_vertices;
6602 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6605 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6606 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6608 if (!r_framedata_failed)
6609 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6615 // see if this ent is worth caching
6616 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6618 // get some memory for this entity and generate mesh data
6619 numvertices = model->surfmesh.num_vertices;
6620 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6622 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6625 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6626 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6628 if (!r_framedata_failed)
6629 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6631 return !r_framedata_failed;
6634 void R_AnimCache_CacheVisibleEntities(void)
6637 qboolean wantnormals = !r_showsurfaces.integer;
6638 qboolean wanttangents = !r_showsurfaces.integer;
6640 switch(vid.renderpath)
6642 case RENDERPATH_GL20:
6643 case RENDERPATH_CGGL:
6645 case RENDERPATH_GL13:
6646 case RENDERPATH_GL11:
6647 wanttangents = false;
6651 // TODO: thread this
6652 // NOTE: R_PrepareRTLights() also caches entities
6654 for (i = 0;i < r_refdef.scene.numentities;i++)
6655 if (r_refdef.viewcache.entityvisible[i])
6656 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6659 //==================================================================================
6661 static void R_View_UpdateEntityLighting (void)
6664 entity_render_t *ent;
6665 vec3_t tempdiffusenormal, avg;
6666 vec_t f, fa, fd, fdd;
6667 qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
6669 for (i = 0;i < r_refdef.scene.numentities;i++)
6671 ent = r_refdef.scene.entities[i];
6673 // skip unseen models
6674 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6678 if (ent->model && ent->model->brush.num_leafs)
6680 // TODO: use modellight for r_ambient settings on world?
6681 VectorSet(ent->modellight_ambient, 0, 0, 0);
6682 VectorSet(ent->modellight_diffuse, 0, 0, 0);
6683 VectorSet(ent->modellight_lightdir, 0, 0, 1);
6687 // fetch the lighting from the worldmodel data
6688 VectorClear(ent->modellight_ambient);
6689 VectorClear(ent->modellight_diffuse);
6690 VectorClear(tempdiffusenormal);
6691 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6694 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6695 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6696 if(ent->flags & RENDER_EQUALIZE)
6698 // first fix up ambient lighting...
6699 if(r_equalize_entities_minambient.value > 0)
6701 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6704 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6705 if(fa < r_equalize_entities_minambient.value * fd)
6708 // fa'/fd' = minambient
6709 // fa'+0.25*fd' = fa+0.25*fd
6711 // fa' = fd' * minambient
6712 // fd'*(0.25+minambient) = fa+0.25*fd
6714 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6715 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6717 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6718 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
6719 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6720 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6725 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6727 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6728 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6731 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6732 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6733 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6739 VectorSet(ent->modellight_ambient, 1, 1, 1);
6741 // move the light direction into modelspace coordinates for lighting code
6742 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6743 if(VectorLength2(ent->modellight_lightdir) == 0)
6744 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6745 VectorNormalize(ent->modellight_lightdir);
6749 #define MAX_LINEOFSIGHTTRACES 64
6751 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6754 vec3_t boxmins, boxmaxs;
6757 dp_model_t *model = r_refdef.scene.worldmodel;
6759 if (!model || !model->brush.TraceLineOfSight)
6762 // expand the box a little
6763 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6764 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6765 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6766 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6767 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6768 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6770 // return true if eye is inside enlarged box
6771 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6775 VectorCopy(eye, start);
6776 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6777 if (model->brush.TraceLineOfSight(model, start, end))
6780 // try various random positions
6781 for (i = 0;i < numsamples;i++)
6783 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6784 if (model->brush.TraceLineOfSight(model, start, end))
6792 static void R_View_UpdateEntityVisible (void)
6797 entity_render_t *ent;
6799 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6800 if (!r_drawviewmodel.integer)
6801 renderimask |= RENDER_VIEWMODEL;
6802 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6804 // worldmodel can check visibility
6805 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6806 for (i = 0;i < r_refdef.scene.numentities;i++)
6808 ent = r_refdef.scene.entities[i];
6809 if (!(ent->flags & renderimask))
6810 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)))
6811 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))
6812 r_refdef.viewcache.entityvisible[i] = true;
6814 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6816 for (i = 0;i < r_refdef.scene.numentities;i++)
6818 ent = r_refdef.scene.entities[i];
6819 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6821 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6823 continue; // temp entities do pvs only
6824 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6825 ent->last_trace_visibility = realtime;
6826 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6827 r_refdef.viewcache.entityvisible[i] = 0;
6834 // no worldmodel or it can't check visibility
6835 for (i = 0;i < r_refdef.scene.numentities;i++)
6837 ent = r_refdef.scene.entities[i];
6838 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));
6843 /// only used if skyrendermasked, and normally returns false
6844 int R_DrawBrushModelsSky (void)
6847 entity_render_t *ent;
6850 for (i = 0;i < r_refdef.scene.numentities;i++)
6852 if (!r_refdef.viewcache.entityvisible[i])
6854 ent = r_refdef.scene.entities[i];
6855 if (!ent->model || !ent->model->DrawSky)
6857 ent->model->DrawSky(ent);
6863 static void R_DrawNoModel(entity_render_t *ent);
6864 static void R_DrawModels(void)
6867 entity_render_t *ent;
6869 for (i = 0;i < r_refdef.scene.numentities;i++)
6871 if (!r_refdef.viewcache.entityvisible[i])
6873 ent = r_refdef.scene.entities[i];
6874 r_refdef.stats.entities++;
6875 if (ent->model && ent->model->Draw != NULL)
6876 ent->model->Draw(ent);
6882 static void R_DrawModelsDepth(void)
6885 entity_render_t *ent;
6887 for (i = 0;i < r_refdef.scene.numentities;i++)
6889 if (!r_refdef.viewcache.entityvisible[i])
6891 ent = r_refdef.scene.entities[i];
6892 if (ent->model && ent->model->DrawDepth != NULL)
6893 ent->model->DrawDepth(ent);
6897 static void R_DrawModelsDebug(void)
6900 entity_render_t *ent;
6902 for (i = 0;i < r_refdef.scene.numentities;i++)
6904 if (!r_refdef.viewcache.entityvisible[i])
6906 ent = r_refdef.scene.entities[i];
6907 if (ent->model && ent->model->DrawDebug != NULL)
6908 ent->model->DrawDebug(ent);
6912 static void R_DrawModelsAddWaterPlanes(void)
6915 entity_render_t *ent;
6917 for (i = 0;i < r_refdef.scene.numentities;i++)
6919 if (!r_refdef.viewcache.entityvisible[i])
6921 ent = r_refdef.scene.entities[i];
6922 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6923 ent->model->DrawAddWaterPlanes(ent);
6927 static void R_View_SetFrustum(void)
6930 double slopex, slopey;
6931 vec3_t forward, left, up, origin;
6933 // we can't trust r_refdef.view.forward and friends in reflected scenes
6934 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6937 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6938 r_refdef.view.frustum[0].normal[1] = 0 - 0;
6939 r_refdef.view.frustum[0].normal[2] = -1 - 0;
6940 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6941 r_refdef.view.frustum[1].normal[1] = 0 + 0;
6942 r_refdef.view.frustum[1].normal[2] = -1 + 0;
6943 r_refdef.view.frustum[2].normal[0] = 0 - 0;
6944 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6945 r_refdef.view.frustum[2].normal[2] = -1 - 0;
6946 r_refdef.view.frustum[3].normal[0] = 0 + 0;
6947 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6948 r_refdef.view.frustum[3].normal[2] = -1 + 0;
6952 zNear = r_refdef.nearclip;
6953 nudge = 1.0 - 1.0 / (1<<23);
6954 r_refdef.view.frustum[4].normal[0] = 0 - 0;
6955 r_refdef.view.frustum[4].normal[1] = 0 - 0;
6956 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6957 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6958 r_refdef.view.frustum[5].normal[0] = 0 + 0;
6959 r_refdef.view.frustum[5].normal[1] = 0 + 0;
6960 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6961 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6967 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6968 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6969 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6970 r_refdef.view.frustum[0].dist = m[15] - m[12];
6972 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6973 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6974 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6975 r_refdef.view.frustum[1].dist = m[15] + m[12];
6977 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6978 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6979 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6980 r_refdef.view.frustum[2].dist = m[15] - m[13];
6982 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6983 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6984 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6985 r_refdef.view.frustum[3].dist = m[15] + m[13];
6987 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6988 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6989 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6990 r_refdef.view.frustum[4].dist = m[15] - m[14];
6992 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6993 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6994 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6995 r_refdef.view.frustum[5].dist = m[15] + m[14];
6998 if (r_refdef.view.useperspective)
7000 slopex = 1.0 / r_refdef.view.frustum_x;
7001 slopey = 1.0 / r_refdef.view.frustum_y;
7002 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7003 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
7004 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
7005 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
7006 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7008 // Leaving those out was a mistake, those were in the old code, and they
7009 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7010 // I couldn't reproduce it after adding those normalizations. --blub
7011 VectorNormalize(r_refdef.view.frustum[0].normal);
7012 VectorNormalize(r_refdef.view.frustum[1].normal);
7013 VectorNormalize(r_refdef.view.frustum[2].normal);
7014 VectorNormalize(r_refdef.view.frustum[3].normal);
7016 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7017 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]);
7018 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]);
7019 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]);
7020 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]);
7022 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7023 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7024 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7025 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7026 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7030 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7031 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7032 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7033 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7034 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7035 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7036 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7037 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7038 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7039 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7041 r_refdef.view.numfrustumplanes = 5;
7043 if (r_refdef.view.useclipplane)
7045 r_refdef.view.numfrustumplanes = 6;
7046 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7049 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7050 PlaneClassify(r_refdef.view.frustum + i);
7052 // LordHavoc: note to all quake engine coders, Quake had a special case
7053 // for 90 degrees which assumed a square view (wrong), so I removed it,
7054 // Quake2 has it disabled as well.
7056 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7057 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7058 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7059 //PlaneClassify(&frustum[0]);
7061 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7062 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7063 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7064 //PlaneClassify(&frustum[1]);
7066 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7067 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7068 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7069 //PlaneClassify(&frustum[2]);
7071 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7072 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7073 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7074 //PlaneClassify(&frustum[3]);
7077 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7078 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7079 //PlaneClassify(&frustum[4]);
7082 void R_View_Update(void)
7084 R_Main_ResizeViewCache();
7085 R_View_SetFrustum();
7086 R_View_WorldVisibility(r_refdef.view.useclipplane);
7087 R_View_UpdateEntityVisible();
7088 R_View_UpdateEntityLighting();
7091 void R_SetupView(qboolean allowwaterclippingplane)
7093 const float *customclipplane = NULL;
7095 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7097 // LordHavoc: couldn't figure out how to make this approach the
7098 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7099 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7100 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7101 dist = r_refdef.view.clipplane.dist;
7102 plane[0] = r_refdef.view.clipplane.normal[0];
7103 plane[1] = r_refdef.view.clipplane.normal[1];
7104 plane[2] = r_refdef.view.clipplane.normal[2];
7106 customclipplane = plane;
7109 if (!r_refdef.view.useperspective)
7110 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);
7111 else if (vid.stencil && r_useinfinitefarclip.integer)
7112 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);
7114 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);
7115 R_SetViewport(&r_refdef.view.viewport);
7118 void R_EntityMatrix(const matrix4x4_t *matrix)
7120 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7122 gl_modelmatrixchanged = false;
7123 gl_modelmatrix = *matrix;
7124 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7125 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7126 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7127 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7129 switch(vid.renderpath)
7131 case RENDERPATH_GL20:
7132 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7133 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7134 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7136 case RENDERPATH_CGGL:
7139 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7140 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7141 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7144 case RENDERPATH_GL13:
7145 case RENDERPATH_GL11:
7146 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7152 void R_ResetViewRendering2D(void)
7154 r_viewport_t viewport;
7157 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7158 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);
7159 R_SetViewport(&viewport);
7160 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7161 GL_Color(1, 1, 1, 1);
7162 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7163 GL_BlendFunc(GL_ONE, GL_ZERO);
7164 GL_AlphaTest(false);
7165 GL_ScissorTest(false);
7166 GL_DepthMask(false);
7167 GL_DepthRange(0, 1);
7168 GL_DepthTest(false);
7169 R_EntityMatrix(&identitymatrix);
7170 R_Mesh_ResetTextureState();
7171 GL_PolygonOffset(0, 0);
7172 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7173 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7174 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7175 qglStencilMask(~0);CHECKGLERROR
7176 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7177 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7178 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7181 void R_ResetViewRendering3D(void)
7186 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7187 GL_Color(1, 1, 1, 1);
7188 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7189 GL_BlendFunc(GL_ONE, GL_ZERO);
7190 GL_AlphaTest(false);
7191 GL_ScissorTest(true);
7193 GL_DepthRange(0, 1);
7195 R_EntityMatrix(&identitymatrix);
7196 R_Mesh_ResetTextureState();
7197 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7198 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7199 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7200 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7201 qglStencilMask(~0);CHECKGLERROR
7202 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7203 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7204 GL_CullFace(r_refdef.view.cullface_back);
7207 void R_RenderScene(void);
7208 void R_RenderWaterPlanes(void);
7210 static void R_Water_StartFrame(void)
7213 int waterwidth, waterheight, texturewidth, textureheight;
7214 r_waterstate_waterplane_t *p;
7216 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7219 switch(vid.renderpath)
7221 case RENDERPATH_GL20:
7222 case RENDERPATH_CGGL:
7224 case RENDERPATH_GL13:
7225 case RENDERPATH_GL11:
7229 // set waterwidth and waterheight to the water resolution that will be
7230 // used (often less than the screen resolution for faster rendering)
7231 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7232 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7234 // calculate desired texture sizes
7235 // can't use water if the card does not support the texture size
7236 if (!r_water.integer || r_showsurfaces.integer)
7237 texturewidth = textureheight = waterwidth = waterheight = 0;
7238 else if (vid.support.arb_texture_non_power_of_two)
7240 texturewidth = waterwidth;
7241 textureheight = waterheight;
7245 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
7246 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
7249 // allocate textures as needed
7250 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
7252 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7253 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7255 if (p->texture_refraction)
7256 R_FreeTexture(p->texture_refraction);
7257 p->texture_refraction = NULL;
7258 if (p->texture_reflection)
7259 R_FreeTexture(p->texture_reflection);
7260 p->texture_reflection = NULL;
7262 memset(&r_waterstate, 0, sizeof(r_waterstate));
7263 r_waterstate.texturewidth = texturewidth;
7264 r_waterstate.textureheight = textureheight;
7267 if (r_waterstate.texturewidth)
7269 r_waterstate.enabled = true;
7271 // when doing a reduced render (HDR) we want to use a smaller area
7272 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7273 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7275 // set up variables that will be used in shader setup
7276 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7277 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7278 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7279 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7282 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7283 r_waterstate.numwaterplanes = 0;
7286 void R_Water_AddWaterPlane(msurface_t *surface)
7288 int triangleindex, planeindex;
7294 r_waterstate_waterplane_t *p;
7295 texture_t *t = R_GetCurrentTexture(surface->texture);
7296 // just use the first triangle with a valid normal for any decisions
7297 VectorClear(normal);
7298 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7300 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7301 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7302 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7303 TriangleNormal(vert[0], vert[1], vert[2], normal);
7304 if (VectorLength2(normal) >= 0.001)
7308 VectorCopy(normal, plane.normal);
7309 VectorNormalize(plane.normal);
7310 plane.dist = DotProduct(vert[0], plane.normal);
7311 PlaneClassify(&plane);
7312 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7314 // skip backfaces (except if nocullface is set)
7315 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7317 VectorNegate(plane.normal, plane.normal);
7319 PlaneClassify(&plane);
7323 // find a matching plane if there is one
7324 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7325 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7327 if (planeindex >= r_waterstate.maxwaterplanes)
7328 return; // nothing we can do, out of planes
7330 // if this triangle does not fit any known plane rendered this frame, add one
7331 if (planeindex >= r_waterstate.numwaterplanes)
7333 // store the new plane
7334 r_waterstate.numwaterplanes++;
7336 // clear materialflags and pvs
7337 p->materialflags = 0;
7338 p->pvsvalid = false;
7340 // merge this surface's materialflags into the waterplane
7341 p->materialflags |= t->currentmaterialflags;
7342 // merge this surface's PVS into the waterplane
7343 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7344 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7345 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7347 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7352 static void R_Water_ProcessPlanes(void)
7354 r_refdef_view_t originalview;
7355 r_refdef_view_t myview;
7357 r_waterstate_waterplane_t *p;
7359 originalview = r_refdef.view;
7361 // make sure enough textures are allocated
7362 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7364 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7366 if (!p->texture_refraction)
7367 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);
7368 if (!p->texture_refraction)
7372 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7374 if (!p->texture_reflection)
7375 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);
7376 if (!p->texture_reflection)
7382 r_refdef.view = originalview;
7383 r_refdef.view.showdebug = false;
7384 r_refdef.view.width = r_waterstate.waterwidth;
7385 r_refdef.view.height = r_waterstate.waterheight;
7386 r_refdef.view.useclipplane = true;
7387 myview = r_refdef.view;
7388 r_waterstate.renderingscene = true;
7389 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7391 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7393 r_refdef.view = myview;
7394 // render reflected scene and copy into texture
7395 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7396 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7397 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7398 r_refdef.view.clipplane = p->plane;
7399 // reverse the cullface settings for this render
7400 r_refdef.view.cullface_front = GL_FRONT;
7401 r_refdef.view.cullface_back = GL_BACK;
7402 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7404 r_refdef.view.usecustompvs = true;
7406 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7408 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7411 R_ResetViewRendering3D();
7412 R_ClearScreen(r_refdef.fogenabled);
7416 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);
7419 // render the normal view scene and copy into texture
7420 // (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)
7421 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7423 r_refdef.view = myview;
7424 r_refdef.view.clipplane = p->plane;
7425 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7426 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7427 PlaneClassify(&r_refdef.view.clipplane);
7429 R_ResetViewRendering3D();
7430 R_ClearScreen(r_refdef.fogenabled);
7434 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);
7438 r_waterstate.renderingscene = false;
7439 r_refdef.view = originalview;
7440 R_ResetViewRendering3D();
7441 R_ClearScreen(r_refdef.fogenabled);
7445 r_refdef.view = originalview;
7446 r_waterstate.renderingscene = false;
7447 Cvar_SetValueQuick(&r_water, 0);
7448 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
7452 void R_Bloom_StartFrame(void)
7454 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7456 switch(vid.renderpath)
7458 case RENDERPATH_GL20:
7459 case RENDERPATH_CGGL:
7461 case RENDERPATH_GL13:
7462 case RENDERPATH_GL11:
7466 // set bloomwidth and bloomheight to the bloom resolution that will be
7467 // used (often less than the screen resolution for faster rendering)
7468 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7469 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7470 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7471 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7472 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7474 // calculate desired texture sizes
7475 if (vid.support.arb_texture_non_power_of_two)
7477 screentexturewidth = r_refdef.view.width;
7478 screentextureheight = r_refdef.view.height;
7479 bloomtexturewidth = r_bloomstate.bloomwidth;
7480 bloomtextureheight = r_bloomstate.bloomheight;
7484 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
7485 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
7486 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
7487 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
7490 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))
7492 Cvar_SetValueQuick(&r_hdr, 0);
7493 Cvar_SetValueQuick(&r_bloom, 0);
7494 Cvar_SetValueQuick(&r_motionblur, 0);
7495 Cvar_SetValueQuick(&r_damageblur, 0);
7498 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)))
7499 screentexturewidth = screentextureheight = 0;
7500 if (!r_hdr.integer && !r_bloom.integer)
7501 bloomtexturewidth = bloomtextureheight = 0;
7503 // allocate textures as needed
7504 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7506 if (r_bloomstate.texture_screen)
7507 R_FreeTexture(r_bloomstate.texture_screen);
7508 r_bloomstate.texture_screen = NULL;
7509 r_bloomstate.screentexturewidth = screentexturewidth;
7510 r_bloomstate.screentextureheight = screentextureheight;
7511 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7512 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7514 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7516 if (r_bloomstate.texture_bloom)
7517 R_FreeTexture(r_bloomstate.texture_bloom);
7518 r_bloomstate.texture_bloom = NULL;
7519 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7520 r_bloomstate.bloomtextureheight = bloomtextureheight;
7521 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7522 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7525 // when doing a reduced render (HDR) we want to use a smaller area
7526 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7527 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7528 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7529 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7530 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7532 // set up a texcoord array for the full resolution screen image
7533 // (we have to keep this around to copy back during final render)
7534 r_bloomstate.screentexcoord2f[0] = 0;
7535 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7536 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7537 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7538 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7539 r_bloomstate.screentexcoord2f[5] = 0;
7540 r_bloomstate.screentexcoord2f[6] = 0;
7541 r_bloomstate.screentexcoord2f[7] = 0;
7543 // set up a texcoord array for the reduced resolution bloom image
7544 // (which will be additive blended over the screen image)
7545 r_bloomstate.bloomtexcoord2f[0] = 0;
7546 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7547 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7548 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7549 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7550 r_bloomstate.bloomtexcoord2f[5] = 0;
7551 r_bloomstate.bloomtexcoord2f[6] = 0;
7552 r_bloomstate.bloomtexcoord2f[7] = 0;
7554 if (r_hdr.integer || r_bloom.integer)
7556 r_bloomstate.enabled = true;
7557 r_bloomstate.hdr = r_hdr.integer != 0;
7560 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);
7563 void R_Bloom_CopyBloomTexture(float colorscale)
7565 r_refdef.stats.bloom++;
7567 // scale down screen texture to the bloom texture size
7569 R_SetViewport(&r_bloomstate.viewport);
7570 GL_BlendFunc(GL_ONE, GL_ZERO);
7571 GL_Color(colorscale, colorscale, colorscale, 1);
7572 // TODO: optimize with multitexture or GLSL
7573 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7574 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7575 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7576 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7578 // we now have a bloom image in the framebuffer
7579 // copy it into the bloom image texture for later processing
7580 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);
7581 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7584 void R_Bloom_CopyHDRTexture(void)
7586 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);
7587 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7590 void R_Bloom_MakeTexture(void)
7593 float xoffset, yoffset, r, brighten;
7595 r_refdef.stats.bloom++;
7597 R_ResetViewRendering2D();
7598 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7599 R_Mesh_ColorPointer(NULL, 0, 0);
7601 // we have a bloom image in the framebuffer
7603 R_SetViewport(&r_bloomstate.viewport);
7605 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7608 r = bound(0, r_bloom_colorexponent.value / x, 1);
7609 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7610 GL_Color(r, r, r, 1);
7611 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7612 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7613 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7614 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7616 // copy the vertically blurred bloom view to a texture
7617 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);
7618 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7621 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7622 brighten = r_bloom_brighten.value;
7624 brighten *= r_hdr_range.value;
7625 brighten = sqrt(brighten);
7627 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7628 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7629 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7631 for (dir = 0;dir < 2;dir++)
7633 // blend on at multiple vertical offsets to achieve a vertical blur
7634 // TODO: do offset blends using GLSL
7635 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7636 GL_BlendFunc(GL_ONE, GL_ZERO);
7637 for (x = -range;x <= range;x++)
7639 if (!dir){xoffset = 0;yoffset = x;}
7640 else {xoffset = x;yoffset = 0;}
7641 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7642 yoffset /= (float)r_bloomstate.bloomtextureheight;
7643 // compute a texcoord array with the specified x and y offset
7644 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7645 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7646 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7647 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7648 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7649 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7650 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7651 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7652 // this r value looks like a 'dot' particle, fading sharply to
7653 // black at the edges
7654 // (probably not realistic but looks good enough)
7655 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7656 //r = brighten/(range*2+1);
7657 r = brighten / (range * 2 + 1);
7659 r *= (1 - x*x/(float)(range*range));
7660 GL_Color(r, r, r, 1);
7661 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7662 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7663 GL_BlendFunc(GL_ONE, GL_ONE);
7666 // copy the vertically blurred bloom view to a texture
7667 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);
7668 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7671 // apply subtract last
7672 // (just like it would be in a GLSL shader)
7673 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7675 GL_BlendFunc(GL_ONE, GL_ZERO);
7676 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7677 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7678 GL_Color(1, 1, 1, 1);
7679 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7680 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7682 GL_BlendFunc(GL_ONE, GL_ONE);
7683 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7684 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7685 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7686 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7687 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7688 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7689 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7691 // copy the darkened bloom view to a texture
7692 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);
7693 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7697 void R_HDR_RenderBloomTexture(void)
7699 int oldwidth, oldheight;
7700 float oldcolorscale;
7702 oldcolorscale = r_refdef.view.colorscale;
7703 oldwidth = r_refdef.view.width;
7704 oldheight = r_refdef.view.height;
7705 r_refdef.view.width = r_bloomstate.bloomwidth;
7706 r_refdef.view.height = r_bloomstate.bloomheight;
7708 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
7709 // TODO: add exposure compensation features
7710 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7712 r_refdef.view.showdebug = false;
7713 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7715 R_ResetViewRendering3D();
7717 R_ClearScreen(r_refdef.fogenabled);
7718 if (r_timereport_active)
7719 R_TimeReport("HDRclear");
7722 if (r_timereport_active)
7723 R_TimeReport("visibility");
7725 // only do secondary renders with HDR if r_hdr is 2 or higher
7726 r_waterstate.numwaterplanes = 0;
7727 if (r_waterstate.enabled && r_hdr.integer >= 2)
7728 R_RenderWaterPlanes();
7730 r_refdef.view.showdebug = true;
7732 r_waterstate.numwaterplanes = 0;
7734 R_ResetViewRendering2D();
7736 R_Bloom_CopyHDRTexture();
7737 R_Bloom_MakeTexture();
7739 // restore the view settings
7740 r_refdef.view.width = oldwidth;
7741 r_refdef.view.height = oldheight;
7742 r_refdef.view.colorscale = oldcolorscale;
7744 R_ResetViewRendering3D();
7746 R_ClearScreen(r_refdef.fogenabled);
7747 if (r_timereport_active)
7748 R_TimeReport("viewclear");
7751 static void R_BlendView(void)
7753 unsigned int permutation;
7754 float uservecs[4][4];
7756 switch (vid.renderpath)
7758 case RENDERPATH_GL20:
7759 case RENDERPATH_CGGL:
7761 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7762 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7763 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7764 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7765 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7767 if (r_bloomstate.texture_screen)
7769 // make sure the buffer is available
7770 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7772 R_ResetViewRendering2D();
7773 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7774 R_Mesh_ColorPointer(NULL, 0, 0);
7776 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7778 // declare variables
7780 static float avgspeed;
7782 speed = VectorLength(cl.movement_velocity);
7784 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7785 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7787 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7788 speed = bound(0, speed, 1);
7789 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7791 // calculate values into a standard alpha
7792 cl.motionbluralpha = 1 - exp(-
7794 (r_motionblur.value * speed / 80)
7796 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7799 max(0.0001, cl.time - cl.oldtime) // fps independent
7802 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7803 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7805 if (cl.motionbluralpha > 0)
7807 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7808 GL_Color(1, 1, 1, cl.motionbluralpha);
7809 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7810 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7811 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7812 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7816 // copy view into the screen texture
7817 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);
7818 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7820 else if (!r_bloomstate.texture_bloom)
7822 // we may still have to do view tint...
7823 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7825 // apply a color tint to the whole view
7826 R_ResetViewRendering2D();
7827 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7828 R_Mesh_ColorPointer(NULL, 0, 0);
7829 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7830 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7831 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7832 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7834 break; // no screen processing, no bloom, skip it
7837 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7839 // render simple bloom effect
7840 // copy the screen and shrink it and darken it for the bloom process
7841 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7842 // make the bloom texture
7843 R_Bloom_MakeTexture();
7846 #if _MSC_VER >= 1400
7847 #define sscanf sscanf_s
7849 memset(uservecs, 0, sizeof(uservecs));
7850 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7851 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7852 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7853 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7855 R_ResetViewRendering2D();
7856 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7857 R_Mesh_ColorPointer(NULL, 0, 0);
7858 GL_Color(1, 1, 1, 1);
7859 GL_BlendFunc(GL_ONE, GL_ZERO);
7860 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7861 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7863 switch(vid.renderpath)
7865 case RENDERPATH_GL20:
7866 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7867 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
7868 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
7869 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7870 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]);
7871 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7872 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]);
7873 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]);
7874 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]);
7875 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]);
7876 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7877 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7879 case RENDERPATH_CGGL:
7881 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7882 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
7883 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
7884 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
7885 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
7886 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7887 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
7888 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
7889 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
7890 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
7891 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
7892 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7898 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7899 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7901 case RENDERPATH_GL13:
7902 case RENDERPATH_GL11:
7903 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7905 // apply a color tint to the whole view
7906 R_ResetViewRendering2D();
7907 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7908 R_Mesh_ColorPointer(NULL, 0, 0);
7909 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7910 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7911 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7912 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7918 matrix4x4_t r_waterscrollmatrix;
7920 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7922 if (r_refdef.fog_density)
7924 r_refdef.fogcolor[0] = r_refdef.fog_red;
7925 r_refdef.fogcolor[1] = r_refdef.fog_green;
7926 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7928 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7929 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7930 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7931 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7935 VectorCopy(r_refdef.fogcolor, fogvec);
7936 // color.rgb *= ContrastBoost * SceneBrightness;
7937 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7938 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7939 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7940 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7945 void R_UpdateVariables(void)
7949 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7951 r_refdef.farclip = r_farclip_base.value;
7952 if (r_refdef.scene.worldmodel)
7953 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7954 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7956 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7957 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7958 r_refdef.polygonfactor = 0;
7959 r_refdef.polygonoffset = 0;
7960 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7961 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7963 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7964 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7965 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7966 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7967 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7968 if (r_showsurfaces.integer)
7970 r_refdef.scene.rtworld = false;
7971 r_refdef.scene.rtworldshadows = false;
7972 r_refdef.scene.rtdlight = false;
7973 r_refdef.scene.rtdlightshadows = false;
7974 r_refdef.lightmapintensity = 0;
7977 if (gamemode == GAME_NEHAHRA)
7979 if (gl_fogenable.integer)
7981 r_refdef.oldgl_fogenable = true;
7982 r_refdef.fog_density = gl_fogdensity.value;
7983 r_refdef.fog_red = gl_fogred.value;
7984 r_refdef.fog_green = gl_foggreen.value;
7985 r_refdef.fog_blue = gl_fogblue.value;
7986 r_refdef.fog_alpha = 1;
7987 r_refdef.fog_start = 0;
7988 r_refdef.fog_end = gl_skyclip.value;
7989 r_refdef.fog_height = 1<<30;
7990 r_refdef.fog_fadedepth = 128;
7992 else if (r_refdef.oldgl_fogenable)
7994 r_refdef.oldgl_fogenable = false;
7995 r_refdef.fog_density = 0;
7996 r_refdef.fog_red = 0;
7997 r_refdef.fog_green = 0;
7998 r_refdef.fog_blue = 0;
7999 r_refdef.fog_alpha = 0;
8000 r_refdef.fog_start = 0;
8001 r_refdef.fog_end = 0;
8002 r_refdef.fog_height = 1<<30;
8003 r_refdef.fog_fadedepth = 128;
8007 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8008 r_refdef.fog_start = max(0, r_refdef.fog_start);
8009 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8011 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8013 if (r_refdef.fog_density && r_drawfog.integer)
8015 r_refdef.fogenabled = true;
8016 // this is the point where the fog reaches 0.9986 alpha, which we
8017 // consider a good enough cutoff point for the texture
8018 // (0.9986 * 256 == 255.6)
8019 if (r_fog_exp2.integer)
8020 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8022 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8023 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8024 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8025 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8026 // fog color was already set
8027 // update the fog texture
8028 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)
8029 R_BuildFogTexture();
8032 r_refdef.fogenabled = false;
8034 switch(vid.renderpath)
8036 case RENDERPATH_GL20:
8037 case RENDERPATH_CGGL:
8038 if(v_glslgamma.integer && !vid_gammatables_trivial)
8040 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8042 // build GLSL gamma texture
8043 #define RAMPWIDTH 256
8044 unsigned short ramp[RAMPWIDTH * 3];
8045 unsigned char rampbgr[RAMPWIDTH][4];
8048 r_texture_gammaramps_serial = vid_gammatables_serial;
8050 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8051 for(i = 0; i < RAMPWIDTH; ++i)
8053 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8054 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8055 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8058 if (r_texture_gammaramps)
8060 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8064 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);
8070 // remove GLSL gamma texture
8073 case RENDERPATH_GL13:
8074 case RENDERPATH_GL11:
8079 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8080 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8086 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8087 if( scenetype != r_currentscenetype ) {
8088 // store the old scenetype
8089 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8090 r_currentscenetype = scenetype;
8091 // move in the new scene
8092 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8101 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8103 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8104 if( scenetype == r_currentscenetype ) {
8105 return &r_refdef.scene;
8107 return &r_scenes_store[ scenetype ];
8116 void R_RenderView(void)
8118 if (r_timereport_active)
8119 R_TimeReport("start");
8120 r_textureframe++; // used only by R_GetCurrentTexture
8121 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8123 if (!r_drawentities.integer)
8124 r_refdef.scene.numentities = 0;
8126 R_AnimCache_ClearCache();
8127 R_FrameData_NewFrame();
8129 if (r_refdef.view.isoverlay)
8131 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8132 GL_Clear( GL_DEPTH_BUFFER_BIT );
8133 R_TimeReport("depthclear");
8135 r_refdef.view.showdebug = false;
8137 r_waterstate.enabled = false;
8138 r_waterstate.numwaterplanes = 0;
8146 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8147 return; //Host_Error ("R_RenderView: NULL worldmodel");
8149 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8151 // break apart the view matrix into vectors for various purposes
8152 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8153 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8154 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8155 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8156 // make an inverted copy of the view matrix for tracking sprites
8157 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8159 R_Shadow_UpdateWorldLightSelection();
8161 R_Bloom_StartFrame();
8162 R_Water_StartFrame();
8165 if (r_timereport_active)
8166 R_TimeReport("viewsetup");
8168 R_ResetViewRendering3D();
8170 if (r_refdef.view.clear || r_refdef.fogenabled)
8172 R_ClearScreen(r_refdef.fogenabled);
8173 if (r_timereport_active)
8174 R_TimeReport("viewclear");
8176 r_refdef.view.clear = true;
8178 // this produces a bloom texture to be used in R_BlendView() later
8179 if (r_hdr.integer && r_bloomstate.bloomwidth)
8181 R_HDR_RenderBloomTexture();
8182 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8183 r_textureframe++; // used only by R_GetCurrentTexture
8186 r_refdef.view.showdebug = true;
8189 if (r_timereport_active)
8190 R_TimeReport("visibility");
8192 r_waterstate.numwaterplanes = 0;
8193 if (r_waterstate.enabled)
8194 R_RenderWaterPlanes();
8197 r_waterstate.numwaterplanes = 0;
8200 if (r_timereport_active)
8201 R_TimeReport("blendview");
8203 GL_Scissor(0, 0, vid.width, vid.height);
8204 GL_ScissorTest(false);
8208 void R_RenderWaterPlanes(void)
8210 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8212 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8213 if (r_timereport_active)
8214 R_TimeReport("waterworld");
8217 // don't let sound skip if going slow
8218 if (r_refdef.scene.extraupdate)
8221 R_DrawModelsAddWaterPlanes();
8222 if (r_timereport_active)
8223 R_TimeReport("watermodels");
8225 if (r_waterstate.numwaterplanes)
8227 R_Water_ProcessPlanes();
8228 if (r_timereport_active)
8229 R_TimeReport("waterscenes");
8233 extern void R_DrawLightningBeams (void);
8234 extern void VM_CL_AddPolygonsToMeshQueue (void);
8235 extern void R_DrawPortals (void);
8236 extern cvar_t cl_locs_show;
8237 static void R_DrawLocs(void);
8238 static void R_DrawEntityBBoxes(void);
8239 static void R_DrawModelDecals(void);
8240 extern void R_DrawModelShadows(void);
8241 extern void R_DrawModelShadowMaps(void);
8242 extern cvar_t cl_decals_newsystem;
8243 extern qboolean r_shadow_usingdeferredprepass;
8244 void R_RenderScene(void)
8246 qboolean shadowmapping = false;
8248 r_refdef.stats.renders++;
8252 // don't let sound skip if going slow
8253 if (r_refdef.scene.extraupdate)
8256 R_MeshQueue_BeginScene();
8260 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);
8262 if (cl.csqc_vidvars.drawworld)
8264 // don't let sound skip if going slow
8265 if (r_refdef.scene.extraupdate)
8268 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8270 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8271 if (r_timereport_active)
8272 R_TimeReport("worldsky");
8275 if (R_DrawBrushModelsSky() && r_timereport_active)
8276 R_TimeReport("bmodelsky");
8278 if (skyrendermasked && skyrenderlater)
8280 // we have to force off the water clipping plane while rendering sky
8284 if (r_timereport_active)
8285 R_TimeReport("sky");
8289 R_AnimCache_CacheVisibleEntities();
8290 if (r_timereport_active)
8291 R_TimeReport("animation");
8293 R_Shadow_PrepareLights();
8294 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8295 R_Shadow_PrepareModelShadows();
8296 if (r_timereport_active)
8297 R_TimeReport("preparelights");
8299 if (R_Shadow_ShadowMappingEnabled())
8300 shadowmapping = true;
8302 if (r_shadow_usingdeferredprepass)
8303 R_Shadow_DrawPrepass();
8305 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8307 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8308 if (r_timereport_active)
8309 R_TimeReport("worlddepth");
8311 if (r_depthfirst.integer >= 2)
8313 R_DrawModelsDepth();
8314 if (r_timereport_active)
8315 R_TimeReport("modeldepth");
8318 if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8320 R_DrawModelShadowMaps();
8321 R_ResetViewRendering3D();
8322 // don't let sound skip if going slow
8323 if (r_refdef.scene.extraupdate)
8327 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8329 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8330 if (r_timereport_active)
8331 R_TimeReport("world");
8334 // don't let sound skip if going slow
8335 if (r_refdef.scene.extraupdate)
8339 if (r_timereport_active)
8340 R_TimeReport("models");
8342 // don't let sound skip if going slow
8343 if (r_refdef.scene.extraupdate)
8346 if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8348 R_DrawModelShadows();
8349 R_ResetViewRendering3D();
8350 // don't let sound skip if going slow
8351 if (r_refdef.scene.extraupdate)
8355 if (!r_shadow_usingdeferredprepass)
8357 R_Shadow_DrawLights();
8358 if (r_timereport_active)
8359 R_TimeReport("rtlights");
8362 // don't let sound skip if going slow
8363 if (r_refdef.scene.extraupdate)
8366 if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8368 R_DrawModelShadows();
8369 R_ResetViewRendering3D();
8370 // don't let sound skip if going slow
8371 if (r_refdef.scene.extraupdate)
8375 if (cl.csqc_vidvars.drawworld)
8377 if (cl_decals_newsystem.integer)
8379 R_DrawModelDecals();
8380 if (r_timereport_active)
8381 R_TimeReport("modeldecals");
8386 if (r_timereport_active)
8387 R_TimeReport("decals");
8391 if (r_timereport_active)
8392 R_TimeReport("particles");
8395 if (r_timereport_active)
8396 R_TimeReport("explosions");
8398 R_DrawLightningBeams();
8399 if (r_timereport_active)
8400 R_TimeReport("lightning");
8403 VM_CL_AddPolygonsToMeshQueue();
8405 if (r_refdef.view.showdebug)
8407 if (cl_locs_show.integer)
8410 if (r_timereport_active)
8411 R_TimeReport("showlocs");
8414 if (r_drawportals.integer)
8417 if (r_timereport_active)
8418 R_TimeReport("portals");
8421 if (r_showbboxes.value > 0)
8423 R_DrawEntityBBoxes();
8424 if (r_timereport_active)
8425 R_TimeReport("bboxes");
8429 R_MeshQueue_RenderTransparent();
8430 if (r_timereport_active)
8431 R_TimeReport("drawtrans");
8433 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))
8435 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8436 if (r_timereport_active)
8437 R_TimeReport("worlddebug");
8438 R_DrawModelsDebug();
8439 if (r_timereport_active)
8440 R_TimeReport("modeldebug");
8443 if (cl.csqc_vidvars.drawworld)
8445 R_Shadow_DrawCoronas();
8446 if (r_timereport_active)
8447 R_TimeReport("coronas");
8450 // don't let sound skip if going slow
8451 if (r_refdef.scene.extraupdate)
8454 R_ResetViewRendering2D();
8457 static const unsigned short bboxelements[36] =
8467 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8470 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8472 RSurf_ActiveWorldEntity();
8474 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8475 GL_DepthMask(false);
8476 GL_DepthRange(0, 1);
8477 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8478 R_Mesh_ResetTextureState();
8480 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8481 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8482 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8483 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8484 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8485 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8486 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8487 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8488 R_FillColors(color4f, 8, cr, cg, cb, ca);
8489 if (r_refdef.fogenabled)
8491 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8493 f1 = RSurf_FogVertex(v);
8495 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8496 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8497 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8500 R_Mesh_VertexPointer(vertex3f, 0, 0);
8501 R_Mesh_ColorPointer(color4f, 0, 0);
8502 R_Mesh_ResetTextureState();
8503 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8504 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8507 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8511 prvm_edict_t *edict;
8512 prvm_prog_t *prog_save = prog;
8514 // this function draws bounding boxes of server entities
8518 GL_CullFace(GL_NONE);
8519 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8523 for (i = 0;i < numsurfaces;i++)
8525 edict = PRVM_EDICT_NUM(surfacelist[i]);
8526 switch ((int)edict->fields.server->solid)
8528 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
8529 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
8530 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
8531 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8532 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
8533 default: Vector4Set(color, 0, 0, 0, 0.50);break;
8535 color[3] *= r_showbboxes.value;
8536 color[3] = bound(0, color[3], 1);
8537 GL_DepthTest(!r_showdisabledepthtest.integer);
8538 GL_CullFace(r_refdef.view.cullface_front);
8539 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8545 static void R_DrawEntityBBoxes(void)
8548 prvm_edict_t *edict;
8550 prvm_prog_t *prog_save = prog;
8552 // this function draws bounding boxes of server entities
8558 for (i = 0;i < prog->num_edicts;i++)
8560 edict = PRVM_EDICT_NUM(i);
8561 if (edict->priv.server->free)
8563 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8564 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8566 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8568 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8569 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8575 static const int nomodelelement3i[24] =
8587 static const unsigned short nomodelelement3s[24] =
8599 static const float nomodelvertex3f[6*3] =
8609 static const float nomodelcolor4f[6*4] =
8611 0.0f, 0.0f, 0.5f, 1.0f,
8612 0.0f, 0.0f, 0.5f, 1.0f,
8613 0.0f, 0.5f, 0.0f, 1.0f,
8614 0.0f, 0.5f, 0.0f, 1.0f,
8615 0.5f, 0.0f, 0.0f, 1.0f,
8616 0.5f, 0.0f, 0.0f, 1.0f
8619 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8625 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);
8627 // this is only called once per entity so numsurfaces is always 1, and
8628 // surfacelist is always {0}, so this code does not handle batches
8630 if (rsurface.ent_flags & RENDER_ADDITIVE)
8632 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8633 GL_DepthMask(false);
8635 else if (rsurface.colormod[3] < 1)
8637 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8638 GL_DepthMask(false);
8642 GL_BlendFunc(GL_ONE, GL_ZERO);
8645 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8646 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8647 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8648 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8649 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8650 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8651 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8652 R_Mesh_ColorPointer(color4f, 0, 0);
8653 for (i = 0, c = color4f;i < 6;i++, c += 4)
8655 c[0] *= rsurface.colormod[0];
8656 c[1] *= rsurface.colormod[1];
8657 c[2] *= rsurface.colormod[2];
8658 c[3] *= rsurface.colormod[3];
8660 if (r_refdef.fogenabled)
8662 for (i = 0, c = color4f;i < 6;i++, c += 4)
8664 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8666 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8667 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8668 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8671 R_Mesh_ResetTextureState();
8672 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8675 void R_DrawNoModel(entity_render_t *ent)
8678 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8679 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8680 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8682 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8685 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8687 vec3_t right1, right2, diff, normal;
8689 VectorSubtract (org2, org1, normal);
8691 // calculate 'right' vector for start
8692 VectorSubtract (r_refdef.view.origin, org1, diff);
8693 CrossProduct (normal, diff, right1);
8694 VectorNormalize (right1);
8696 // calculate 'right' vector for end
8697 VectorSubtract (r_refdef.view.origin, org2, diff);
8698 CrossProduct (normal, diff, right2);
8699 VectorNormalize (right2);
8701 vert[ 0] = org1[0] + width * right1[0];
8702 vert[ 1] = org1[1] + width * right1[1];
8703 vert[ 2] = org1[2] + width * right1[2];
8704 vert[ 3] = org1[0] - width * right1[0];
8705 vert[ 4] = org1[1] - width * right1[1];
8706 vert[ 5] = org1[2] - width * right1[2];
8707 vert[ 6] = org2[0] - width * right2[0];
8708 vert[ 7] = org2[1] - width * right2[1];
8709 vert[ 8] = org2[2] - width * right2[2];
8710 vert[ 9] = org2[0] + width * right2[0];
8711 vert[10] = org2[1] + width * right2[1];
8712 vert[11] = org2[2] + width * right2[2];
8715 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)
8717 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8718 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8719 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8720 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8721 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8722 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8723 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8724 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8725 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8726 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8727 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8728 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8731 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8736 VectorSet(v, x, y, z);
8737 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8738 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8740 if (i == mesh->numvertices)
8742 if (mesh->numvertices < mesh->maxvertices)
8744 VectorCopy(v, vertex3f);
8745 mesh->numvertices++;
8747 return mesh->numvertices;
8753 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8757 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8758 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8759 e = mesh->element3i + mesh->numtriangles * 3;
8760 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8762 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8763 if (mesh->numtriangles < mesh->maxtriangles)
8768 mesh->numtriangles++;
8770 element[1] = element[2];
8774 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8778 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8779 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8780 e = mesh->element3i + mesh->numtriangles * 3;
8781 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8783 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8784 if (mesh->numtriangles < mesh->maxtriangles)
8789 mesh->numtriangles++;
8791 element[1] = element[2];
8795 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8796 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8798 int planenum, planenum2;
8801 mplane_t *plane, *plane2;
8803 double temppoints[2][256*3];
8804 // figure out how large a bounding box we need to properly compute this brush
8806 for (w = 0;w < numplanes;w++)
8807 maxdist = max(maxdist, fabs(planes[w].dist));
8808 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8809 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8810 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8814 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8815 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8817 if (planenum2 == planenum)
8819 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);
8822 if (tempnumpoints < 3)
8824 // generate elements forming a triangle fan for this polygon
8825 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8829 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)
8831 texturelayer_t *layer;
8832 layer = t->currentlayers + t->currentnumlayers++;
8834 layer->depthmask = depthmask;
8835 layer->blendfunc1 = blendfunc1;
8836 layer->blendfunc2 = blendfunc2;
8837 layer->texture = texture;
8838 layer->texmatrix = *matrix;
8839 layer->color[0] = r;
8840 layer->color[1] = g;
8841 layer->color[2] = b;
8842 layer->color[3] = a;
8845 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8848 index = parms[2] + r_refdef.scene.time * parms[3];
8849 index -= floor(index);
8853 case Q3WAVEFUNC_NONE:
8854 case Q3WAVEFUNC_NOISE:
8855 case Q3WAVEFUNC_COUNT:
8858 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8859 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8860 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8861 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8862 case Q3WAVEFUNC_TRIANGLE:
8864 f = index - floor(index);
8875 return (float)(parms[0] + parms[1] * f);
8878 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8883 matrix4x4_t matrix, temp;
8884 switch(tcmod->tcmod)
8888 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8889 matrix = r_waterscrollmatrix;
8891 matrix = identitymatrix;
8893 case Q3TCMOD_ENTITYTRANSLATE:
8894 // this is used in Q3 to allow the gamecode to control texcoord
8895 // scrolling on the entity, which is not supported in darkplaces yet.
8896 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8898 case Q3TCMOD_ROTATE:
8899 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8900 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8901 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8904 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8906 case Q3TCMOD_SCROLL:
8907 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8909 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8910 w = (int) tcmod->parms[0];
8911 h = (int) tcmod->parms[1];
8912 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8914 idx = (int) floor(f * w * h);
8915 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8917 case Q3TCMOD_STRETCH:
8918 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8919 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8921 case Q3TCMOD_TRANSFORM:
8922 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8923 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8924 VectorSet(tcmat + 6, 0 , 0 , 1);
8925 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8926 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8928 case Q3TCMOD_TURBULENT:
8929 // this is handled in the RSurf_PrepareVertices function
8930 matrix = identitymatrix;
8934 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8937 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8939 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8940 char name[MAX_QPATH];
8941 skinframe_t *skinframe;
8942 unsigned char pixels[296*194];
8943 strlcpy(cache->name, skinname, sizeof(cache->name));
8944 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8945 if (developer_loading.integer)
8946 Con_Printf("loading %s\n", name);
8947 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8948 if (!skinframe || !skinframe->base)
8951 fs_offset_t filesize;
8953 f = FS_LoadFile(name, tempmempool, true, &filesize);
8956 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8957 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8961 cache->skinframe = skinframe;
8964 texture_t *R_GetCurrentTexture(texture_t *t)
8967 const entity_render_t *ent = rsurface.entity;
8968 dp_model_t *model = ent->model;
8969 q3shaderinfo_layer_tcmod_t *tcmod;
8971 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8972 return t->currentframe;
8973 t->update_lastrenderframe = r_textureframe;
8974 t->update_lastrenderentity = (void *)ent;
8976 // switch to an alternate material if this is a q1bsp animated material
8978 texture_t *texture = t;
8979 int s = rsurface.ent_skinnum;
8980 if ((unsigned int)s >= (unsigned int)model->numskins)
8982 if (model->skinscenes)
8984 if (model->skinscenes[s].framecount > 1)
8985 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8987 s = model->skinscenes[s].firstframe;
8990 t = t + s * model->num_surfaces;
8993 // use an alternate animation if the entity's frame is not 0,
8994 // and only if the texture has an alternate animation
8995 if (rsurface.ent_alttextures && t->anim_total[1])
8996 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8998 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9000 texture->currentframe = t;
9003 // update currentskinframe to be a qw skin or animation frame
9004 if (rsurface.ent_qwskin >= 0)
9006 i = rsurface.ent_qwskin;
9007 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9009 r_qwskincache_size = cl.maxclients;
9011 Mem_Free(r_qwskincache);
9012 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9014 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9015 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9016 t->currentskinframe = r_qwskincache[i].skinframe;
9017 if (t->currentskinframe == NULL)
9018 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9020 else if (t->numskinframes >= 2)
9021 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9022 if (t->backgroundnumskinframes >= 2)
9023 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9025 t->currentmaterialflags = t->basematerialflags;
9026 t->currentalpha = rsurface.colormod[3];
9027 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9028 t->currentalpha *= r_wateralpha.value;
9029 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9030 t->currentalpha *= t->r_water_wateralpha;
9031 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9032 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
9033 if (!(rsurface.ent_flags & RENDER_LIGHT))
9034 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9035 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9037 // pick a model lighting mode
9038 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9039 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9041 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9043 if (rsurface.ent_flags & RENDER_ADDITIVE)
9044 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9045 else if (t->currentalpha < 1)
9046 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9047 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9048 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9049 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9050 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9051 if (t->backgroundnumskinframes)
9052 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9053 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9055 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
9056 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9059 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
9060 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9061 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9063 // there is no tcmod
9064 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9066 t->currenttexmatrix = r_waterscrollmatrix;
9067 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9069 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9071 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9072 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9075 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9076 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9077 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9078 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9080 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9081 if (t->currentskinframe->qpixels)
9082 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9083 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9084 if (!t->basetexture)
9085 t->basetexture = r_texture_notexture;
9086 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9087 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9088 t->nmaptexture = t->currentskinframe->nmap;
9089 if (!t->nmaptexture)
9090 t->nmaptexture = r_texture_blanknormalmap;
9091 t->glosstexture = r_texture_black;
9092 t->glowtexture = t->currentskinframe->glow;
9093 t->fogtexture = t->currentskinframe->fog;
9094 t->reflectmasktexture = t->currentskinframe->reflect;
9095 if (t->backgroundnumskinframes)
9097 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9098 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9099 t->backgroundglosstexture = r_texture_black;
9100 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9101 if (!t->backgroundnmaptexture)
9102 t->backgroundnmaptexture = r_texture_blanknormalmap;
9106 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9107 t->backgroundnmaptexture = r_texture_blanknormalmap;
9108 t->backgroundglosstexture = r_texture_black;
9109 t->backgroundglowtexture = NULL;
9111 t->specularpower = r_shadow_glossexponent.value;
9112 // TODO: store reference values for these in the texture?
9113 t->specularscale = 0;
9114 if (r_shadow_gloss.integer > 0)
9116 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9118 if (r_shadow_glossintensity.value > 0)
9120 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9121 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9122 t->specularscale = r_shadow_glossintensity.value;
9125 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9127 t->glosstexture = r_texture_white;
9128 t->backgroundglosstexture = r_texture_white;
9129 t->specularscale = r_shadow_gloss2intensity.value;
9130 t->specularpower = r_shadow_gloss2exponent.value;
9133 t->specularscale *= t->specularscalemod;
9134 t->specularpower *= t->specularpowermod;
9136 // lightmaps mode looks bad with dlights using actual texturing, so turn
9137 // off the colormap and glossmap, but leave the normalmap on as it still
9138 // accurately represents the shading involved
9139 if (gl_lightmaps.integer)
9141 t->basetexture = r_texture_grey128;
9142 t->pantstexture = r_texture_black;
9143 t->shirttexture = r_texture_black;
9144 t->nmaptexture = r_texture_blanknormalmap;
9145 t->glosstexture = r_texture_black;
9146 t->glowtexture = NULL;
9147 t->fogtexture = NULL;
9148 t->reflectmasktexture = NULL;
9149 t->backgroundbasetexture = NULL;
9150 t->backgroundnmaptexture = r_texture_blanknormalmap;
9151 t->backgroundglosstexture = r_texture_black;
9152 t->backgroundglowtexture = NULL;
9153 t->specularscale = 0;
9154 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9157 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9158 VectorClear(t->dlightcolor);
9159 t->currentnumlayers = 0;
9160 if (t->currentmaterialflags & MATERIALFLAG_WALL)
9162 int blendfunc1, blendfunc2;
9164 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9166 blendfunc1 = GL_SRC_ALPHA;
9167 blendfunc2 = GL_ONE;
9169 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9171 blendfunc1 = GL_SRC_ALPHA;
9172 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9174 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9176 blendfunc1 = t->customblendfunc[0];
9177 blendfunc2 = t->customblendfunc[1];
9181 blendfunc1 = GL_ONE;
9182 blendfunc2 = GL_ZERO;
9184 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9185 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9187 // fullbright is not affected by r_refdef.lightmapintensity
9188 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]);
9189 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9190 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]);
9191 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9192 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]);
9196 vec3_t ambientcolor;
9198 // set the color tint used for lights affecting this surface
9199 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9201 // q3bsp has no lightmap updates, so the lightstylevalue that
9202 // would normally be baked into the lightmap must be
9203 // applied to the color
9204 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9205 if (model->type == mod_brushq3)
9206 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9207 colorscale *= r_refdef.lightmapintensity;
9208 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9209 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9210 // basic lit geometry
9211 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]);
9212 // add pants/shirt if needed
9213 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9214 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]);
9215 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9216 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]);
9217 // now add ambient passes if needed
9218 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9220 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]);
9221 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9222 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]);
9223 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9224 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]);
9227 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9228 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]);
9229 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9231 // if this is opaque use alpha blend which will darken the earlier
9234 // if this is an alpha blended material, all the earlier passes
9235 // were darkened by fog already, so we only need to add the fog
9236 // color ontop through the fog mask texture
9238 // if this is an additive blended material, all the earlier passes
9239 // were darkened by fog already, and we should not add fog color
9240 // (because the background was not darkened, there is no fog color
9241 // that was lost behind it).
9242 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]);
9246 return t->currentframe;
9249 rsurfacestate_t rsurface;
9251 void R_Mesh_ResizeArrays(int newvertices)
9254 if (rsurface.array_size >= newvertices)
9256 if (rsurface.array_modelvertex3f)
9257 Mem_Free(rsurface.array_modelvertex3f);
9258 rsurface.array_size = (newvertices + 1023) & ~1023;
9259 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9260 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
9261 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
9262 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
9263 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
9264 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
9265 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9266 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9267 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
9268 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
9269 rsurface.array_color4f = base + rsurface.array_size * 27;
9270 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9273 void RSurf_ActiveWorldEntity(void)
9275 dp_model_t *model = r_refdef.scene.worldmodel;
9276 //if (rsurface.entity == r_refdef.scene.worldentity)
9278 rsurface.entity = r_refdef.scene.worldentity;
9279 rsurface.skeleton = NULL;
9280 rsurface.ent_skinnum = 0;
9281 rsurface.ent_qwskin = -1;
9282 rsurface.ent_shadertime = 0;
9283 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9284 if (rsurface.array_size < model->surfmesh.num_vertices)
9285 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9286 rsurface.matrix = identitymatrix;
9287 rsurface.inversematrix = identitymatrix;
9288 rsurface.matrixscale = 1;
9289 rsurface.inversematrixscale = 1;
9290 R_EntityMatrix(&identitymatrix);
9291 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9292 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9293 rsurface.fograngerecip = r_refdef.fograngerecip;
9294 rsurface.fogheightfade = r_refdef.fogheightfade;
9295 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9296 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9297 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9298 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9299 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9300 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9301 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9302 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9303 rsurface.colormod[3] = 1;
9304 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);
9305 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9306 rsurface.frameblend[0].lerp = 1;
9307 rsurface.ent_alttextures = false;
9308 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9309 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9310 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9311 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9312 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9313 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9314 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9315 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9316 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9317 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9318 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9319 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9320 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9321 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9322 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9323 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9324 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9325 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9326 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9327 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9328 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9329 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9330 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9331 rsurface.modelelement3i = model->surfmesh.data_element3i;
9332 rsurface.modelelement3s = model->surfmesh.data_element3s;
9333 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9334 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9335 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9336 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9337 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9338 rsurface.modelsurfaces = model->data_surfaces;
9339 rsurface.generatedvertex = false;
9340 rsurface.vertex3f = rsurface.modelvertex3f;
9341 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9342 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9343 rsurface.svector3f = rsurface.modelsvector3f;
9344 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9345 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9346 rsurface.tvector3f = rsurface.modeltvector3f;
9347 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9348 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9349 rsurface.normal3f = rsurface.modelnormal3f;
9350 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9351 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9352 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9355 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9357 dp_model_t *model = ent->model;
9358 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9360 rsurface.entity = (entity_render_t *)ent;
9361 rsurface.skeleton = ent->skeleton;
9362 rsurface.ent_skinnum = ent->skinnum;
9363 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;
9364 rsurface.ent_shadertime = ent->shadertime;
9365 rsurface.ent_flags = ent->flags;
9366 if (rsurface.array_size < model->surfmesh.num_vertices)
9367 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9368 rsurface.matrix = ent->matrix;
9369 rsurface.inversematrix = ent->inversematrix;
9370 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9371 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9372 R_EntityMatrix(&rsurface.matrix);
9373 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9374 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9375 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9376 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9377 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9378 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9379 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9380 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9381 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9382 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9383 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9384 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9385 rsurface.colormod[3] = ent->alpha;
9386 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9387 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9388 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9389 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9390 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9391 if (ent->model->brush.submodel && !prepass)
9393 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9394 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9396 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9398 if (ent->animcache_vertex3f && !r_framedata_failed)
9400 rsurface.modelvertex3f = ent->animcache_vertex3f;
9401 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9402 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9403 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9405 else if (wanttangents)
9407 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9408 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9409 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9410 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9411 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9413 else if (wantnormals)
9415 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9416 rsurface.modelsvector3f = NULL;
9417 rsurface.modeltvector3f = NULL;
9418 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9419 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9423 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9424 rsurface.modelsvector3f = NULL;
9425 rsurface.modeltvector3f = NULL;
9426 rsurface.modelnormal3f = NULL;
9427 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9429 rsurface.modelvertex3f_bufferobject = 0;
9430 rsurface.modelvertex3f_bufferoffset = 0;
9431 rsurface.modelsvector3f_bufferobject = 0;
9432 rsurface.modelsvector3f_bufferoffset = 0;
9433 rsurface.modeltvector3f_bufferobject = 0;
9434 rsurface.modeltvector3f_bufferoffset = 0;
9435 rsurface.modelnormal3f_bufferobject = 0;
9436 rsurface.modelnormal3f_bufferoffset = 0;
9437 rsurface.generatedvertex = true;
9441 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9442 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9443 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9444 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9445 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9446 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9447 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9448 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9449 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9450 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9451 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9452 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9453 rsurface.generatedvertex = false;
9455 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9456 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9457 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9458 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9459 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9460 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9461 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9462 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9463 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9464 rsurface.modelelement3i = model->surfmesh.data_element3i;
9465 rsurface.modelelement3s = model->surfmesh.data_element3s;
9466 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9467 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9468 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9469 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9470 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9471 rsurface.modelsurfaces = model->data_surfaces;
9472 rsurface.vertex3f = rsurface.modelvertex3f;
9473 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9474 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9475 rsurface.svector3f = rsurface.modelsvector3f;
9476 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9477 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9478 rsurface.tvector3f = rsurface.modeltvector3f;
9479 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9480 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9481 rsurface.normal3f = rsurface.modelnormal3f;
9482 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9483 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9484 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9487 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)
9489 rsurface.entity = r_refdef.scene.worldentity;
9490 rsurface.skeleton = NULL;
9491 rsurface.ent_skinnum = 0;
9492 rsurface.ent_qwskin = -1;
9493 rsurface.ent_shadertime = shadertime;
9494 rsurface.ent_flags = entflags;
9495 rsurface.modelnum_vertices = numvertices;
9496 rsurface.modelnum_triangles = numtriangles;
9497 if (rsurface.array_size < rsurface.modelnum_vertices)
9498 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9499 rsurface.matrix = *matrix;
9500 rsurface.inversematrix = *inversematrix;
9501 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9502 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9503 R_EntityMatrix(&rsurface.matrix);
9504 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9505 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9506 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9507 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9508 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9509 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9510 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9511 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9512 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9513 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9514 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9515 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9516 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);
9517 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9518 rsurface.frameblend[0].lerp = 1;
9519 rsurface.ent_alttextures = false;
9520 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9521 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9524 rsurface.modelvertex3f = vertex3f;
9525 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9526 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9527 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9529 else if (wantnormals)
9531 rsurface.modelvertex3f = vertex3f;
9532 rsurface.modelsvector3f = NULL;
9533 rsurface.modeltvector3f = NULL;
9534 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9538 rsurface.modelvertex3f = vertex3f;
9539 rsurface.modelsvector3f = NULL;
9540 rsurface.modeltvector3f = NULL;
9541 rsurface.modelnormal3f = NULL;
9543 rsurface.modelvertex3f_bufferobject = 0;
9544 rsurface.modelvertex3f_bufferoffset = 0;
9545 rsurface.modelsvector3f_bufferobject = 0;
9546 rsurface.modelsvector3f_bufferoffset = 0;
9547 rsurface.modeltvector3f_bufferobject = 0;
9548 rsurface.modeltvector3f_bufferoffset = 0;
9549 rsurface.modelnormal3f_bufferobject = 0;
9550 rsurface.modelnormal3f_bufferoffset = 0;
9551 rsurface.generatedvertex = true;
9552 rsurface.modellightmapcolor4f = color4f;
9553 rsurface.modellightmapcolor4f_bufferobject = 0;
9554 rsurface.modellightmapcolor4f_bufferoffset = 0;
9555 rsurface.modeltexcoordtexture2f = texcoord2f;
9556 rsurface.modeltexcoordtexture2f_bufferobject = 0;
9557 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9558 rsurface.modeltexcoordlightmap2f = NULL;
9559 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9560 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9561 rsurface.modelelement3i = element3i;
9562 rsurface.modelelement3s = element3s;
9563 rsurface.modelelement3i_bufferobject = 0;
9564 rsurface.modelelement3s_bufferobject = 0;
9565 rsurface.modellightmapoffsets = NULL;
9566 rsurface.modelsurfaces = NULL;
9567 rsurface.vertex3f = rsurface.modelvertex3f;
9568 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9569 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9570 rsurface.svector3f = rsurface.modelsvector3f;
9571 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9572 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9573 rsurface.tvector3f = rsurface.modeltvector3f;
9574 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9575 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9576 rsurface.normal3f = rsurface.modelnormal3f;
9577 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9578 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9579 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9581 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9583 if ((wantnormals || wanttangents) && !normal3f)
9584 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9585 if (wanttangents && !svector3f)
9586 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);
9590 float RSurf_FogPoint(const float *v)
9592 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9593 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9594 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9595 float FogHeightFade = r_refdef.fogheightfade;
9597 unsigned int fogmasktableindex;
9598 if (r_refdef.fogplaneviewabove)
9599 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9601 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9602 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9603 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9606 float RSurf_FogVertex(const float *v)
9608 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9609 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9610 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9611 float FogHeightFade = rsurface.fogheightfade;
9613 unsigned int fogmasktableindex;
9614 if (r_refdef.fogplaneviewabove)
9615 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9617 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9618 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9619 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9622 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9623 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9626 int texturesurfaceindex;
9631 const float *v1, *in_tc;
9633 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9635 q3shaderinfo_deform_t *deform;
9636 // 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
9637 if (rsurface.generatedvertex)
9639 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9640 generatenormals = true;
9641 for (i = 0;i < Q3MAXDEFORMS;i++)
9643 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9645 generatetangents = true;
9646 generatenormals = true;
9648 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9649 generatenormals = true;
9651 if (generatenormals && !rsurface.modelnormal3f)
9653 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9654 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9655 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9656 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9658 if (generatetangents && !rsurface.modelsvector3f)
9660 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9661 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9662 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9663 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9664 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9665 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9666 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);
9669 rsurface.vertex3f = rsurface.modelvertex3f;
9670 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9671 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9672 rsurface.svector3f = rsurface.modelsvector3f;
9673 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9674 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9675 rsurface.tvector3f = rsurface.modeltvector3f;
9676 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9677 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9678 rsurface.normal3f = rsurface.modelnormal3f;
9679 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9680 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9681 // if vertices are deformed (sprite flares and things in maps, possibly
9682 // water waves, bulges and other deformations), generate them into
9683 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9684 // (may be static model data or generated data for an animated model, or
9685 // the previous deform pass)
9686 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9688 switch (deform->deform)
9691 case Q3DEFORM_PROJECTIONSHADOW:
9692 case Q3DEFORM_TEXT0:
9693 case Q3DEFORM_TEXT1:
9694 case Q3DEFORM_TEXT2:
9695 case Q3DEFORM_TEXT3:
9696 case Q3DEFORM_TEXT4:
9697 case Q3DEFORM_TEXT5:
9698 case Q3DEFORM_TEXT6:
9699 case Q3DEFORM_TEXT7:
9702 case Q3DEFORM_AUTOSPRITE:
9703 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9704 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9705 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9706 VectorNormalize(newforward);
9707 VectorNormalize(newright);
9708 VectorNormalize(newup);
9709 // make deformed versions of only the model vertices used by the specified surfaces
9710 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9712 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9713 // a single autosprite surface can contain multiple sprites...
9714 for (j = 0;j < surface->num_vertices - 3;j += 4)
9716 VectorClear(center);
9717 for (i = 0;i < 4;i++)
9718 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9719 VectorScale(center, 0.25f, center);
9720 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9721 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9722 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9723 for (i = 0;i < 4;i++)
9725 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9726 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9729 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);
9730 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);
9732 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9733 rsurface.vertex3f_bufferobject = 0;
9734 rsurface.vertex3f_bufferoffset = 0;
9735 rsurface.svector3f = rsurface.array_deformedsvector3f;
9736 rsurface.svector3f_bufferobject = 0;
9737 rsurface.svector3f_bufferoffset = 0;
9738 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9739 rsurface.tvector3f_bufferobject = 0;
9740 rsurface.tvector3f_bufferoffset = 0;
9741 rsurface.normal3f = rsurface.array_deformednormal3f;
9742 rsurface.normal3f_bufferobject = 0;
9743 rsurface.normal3f_bufferoffset = 0;
9745 case Q3DEFORM_AUTOSPRITE2:
9746 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9747 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9748 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9749 VectorNormalize(newforward);
9750 VectorNormalize(newright);
9751 VectorNormalize(newup);
9752 // make deformed versions of only the model vertices used by the specified surfaces
9753 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9755 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9756 const float *v1, *v2;
9766 memset(shortest, 0, sizeof(shortest));
9767 // a single autosprite surface can contain multiple sprites...
9768 for (j = 0;j < surface->num_vertices - 3;j += 4)
9770 VectorClear(center);
9771 for (i = 0;i < 4;i++)
9772 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9773 VectorScale(center, 0.25f, center);
9774 // find the two shortest edges, then use them to define the
9775 // axis vectors for rotating around the central axis
9776 for (i = 0;i < 6;i++)
9778 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9779 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9781 Debug_PolygonBegin(NULL, 0);
9782 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9783 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);
9784 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9787 l = VectorDistance2(v1, v2);
9788 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9790 l += (1.0f / 1024.0f);
9791 if (shortest[0].length2 > l || i == 0)
9793 shortest[1] = shortest[0];
9794 shortest[0].length2 = l;
9795 shortest[0].v1 = v1;
9796 shortest[0].v2 = v2;
9798 else if (shortest[1].length2 > l || i == 1)
9800 shortest[1].length2 = l;
9801 shortest[1].v1 = v1;
9802 shortest[1].v2 = v2;
9805 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9806 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9808 Debug_PolygonBegin(NULL, 0);
9809 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9810 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);
9811 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9814 // this calculates the right vector from the shortest edge
9815 // and the up vector from the edge midpoints
9816 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9817 VectorNormalize(right);
9818 VectorSubtract(end, start, up);
9819 VectorNormalize(up);
9820 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9821 VectorSubtract(rsurface.localvieworigin, center, forward);
9822 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9823 VectorNegate(forward, forward);
9824 VectorReflect(forward, 0, up, forward);
9825 VectorNormalize(forward);
9826 CrossProduct(up, forward, newright);
9827 VectorNormalize(newright);
9829 Debug_PolygonBegin(NULL, 0);
9830 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);
9831 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9832 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9836 Debug_PolygonBegin(NULL, 0);
9837 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9838 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9839 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9842 // rotate the quad around the up axis vector, this is made
9843 // especially easy by the fact we know the quad is flat,
9844 // so we only have to subtract the center position and
9845 // measure distance along the right vector, and then
9846 // multiply that by the newright vector and add back the
9848 // we also need to subtract the old position to undo the
9849 // displacement from the center, which we do with a
9850 // DotProduct, the subtraction/addition of center is also
9851 // optimized into DotProducts here
9852 l = DotProduct(right, center);
9853 for (i = 0;i < 4;i++)
9855 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9856 f = DotProduct(right, v1) - l;
9857 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9860 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);
9861 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);
9863 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9864 rsurface.vertex3f_bufferobject = 0;
9865 rsurface.vertex3f_bufferoffset = 0;
9866 rsurface.svector3f = rsurface.array_deformedsvector3f;
9867 rsurface.svector3f_bufferobject = 0;
9868 rsurface.svector3f_bufferoffset = 0;
9869 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9870 rsurface.tvector3f_bufferobject = 0;
9871 rsurface.tvector3f_bufferoffset = 0;
9872 rsurface.normal3f = rsurface.array_deformednormal3f;
9873 rsurface.normal3f_bufferobject = 0;
9874 rsurface.normal3f_bufferoffset = 0;
9876 case Q3DEFORM_NORMAL:
9877 // deform the normals to make reflections wavey
9878 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9880 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9881 for (j = 0;j < surface->num_vertices;j++)
9884 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9885 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9886 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9887 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9888 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9889 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9890 VectorNormalize(normal);
9892 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);
9894 rsurface.svector3f = rsurface.array_deformedsvector3f;
9895 rsurface.svector3f_bufferobject = 0;
9896 rsurface.svector3f_bufferoffset = 0;
9897 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9898 rsurface.tvector3f_bufferobject = 0;
9899 rsurface.tvector3f_bufferoffset = 0;
9900 rsurface.normal3f = rsurface.array_deformednormal3f;
9901 rsurface.normal3f_bufferobject = 0;
9902 rsurface.normal3f_bufferoffset = 0;
9905 // deform vertex array to make wavey water and flags and such
9906 waveparms[0] = deform->waveparms[0];
9907 waveparms[1] = deform->waveparms[1];
9908 waveparms[2] = deform->waveparms[2];
9909 waveparms[3] = deform->waveparms[3];
9910 // this is how a divisor of vertex influence on deformation
9911 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9912 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9913 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9915 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9916 for (j = 0;j < surface->num_vertices;j++)
9918 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9919 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9920 // if the wavefunc depends on time, evaluate it per-vertex
9923 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9924 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9926 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9929 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9930 rsurface.vertex3f_bufferobject = 0;
9931 rsurface.vertex3f_bufferoffset = 0;
9933 case Q3DEFORM_BULGE:
9934 // deform vertex array to make the surface have moving bulges
9935 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9937 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9938 for (j = 0;j < surface->num_vertices;j++)
9940 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9941 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9944 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9945 rsurface.vertex3f_bufferobject = 0;
9946 rsurface.vertex3f_bufferoffset = 0;
9949 // deform vertex array
9950 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9951 VectorScale(deform->parms, scale, waveparms);
9952 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9954 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9955 for (j = 0;j < surface->num_vertices;j++)
9956 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9958 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9959 rsurface.vertex3f_bufferobject = 0;
9960 rsurface.vertex3f_bufferoffset = 0;
9964 // generate texcoords based on the chosen texcoord source
9965 switch(rsurface.texture->tcgen.tcgen)
9968 case Q3TCGEN_TEXTURE:
9969 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9970 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
9971 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9973 case Q3TCGEN_LIGHTMAP:
9974 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
9975 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9976 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9978 case Q3TCGEN_VECTOR:
9979 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9981 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9982 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)
9984 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9985 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9988 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9989 rsurface.texcoordtexture2f_bufferobject = 0;
9990 rsurface.texcoordtexture2f_bufferoffset = 0;
9992 case Q3TCGEN_ENVIRONMENT:
9993 // make environment reflections using a spheremap
9994 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9996 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9997 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9998 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9999 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10000 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10002 // identical to Q3A's method, but executed in worldspace so
10003 // carried models can be shiny too
10005 float viewer[3], d, reflected[3], worldreflected[3];
10007 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10008 // VectorNormalize(viewer);
10010 d = DotProduct(normal, viewer);
10012 reflected[0] = normal[0]*2*d - viewer[0];
10013 reflected[1] = normal[1]*2*d - viewer[1];
10014 reflected[2] = normal[2]*2*d - viewer[2];
10015 // note: this is proportinal to viewer, so we can normalize later
10017 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10018 VectorNormalize(worldreflected);
10020 // note: this sphere map only uses world x and z!
10021 // so positive and negative y will LOOK THE SAME.
10022 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10023 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10026 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10027 rsurface.texcoordtexture2f_bufferobject = 0;
10028 rsurface.texcoordtexture2f_bufferoffset = 0;
10031 // the only tcmod that needs software vertex processing is turbulent, so
10032 // check for it here and apply the changes if needed
10033 // and we only support that as the first one
10034 // (handling a mixture of turbulent and other tcmods would be problematic
10035 // without punting it entirely to a software path)
10036 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10038 amplitude = rsurface.texture->tcmods[0].parms[1];
10039 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10040 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10042 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10043 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)
10045 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10046 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10049 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10050 rsurface.texcoordtexture2f_bufferobject = 0;
10051 rsurface.texcoordtexture2f_bufferoffset = 0;
10053 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10054 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10055 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10056 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10059 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10062 const msurface_t *surface = texturesurfacelist[0];
10063 const msurface_t *surface2;
10068 // TODO: lock all array ranges before render, rather than on each surface
10069 if (texturenumsurfaces == 1)
10070 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);
10071 else if (r_batchmode.integer == 2)
10073 #define MAXBATCHTRIANGLES 4096
10074 int batchtriangles = 0;
10075 static int batchelements[MAXBATCHTRIANGLES*3];
10076 for (i = 0;i < texturenumsurfaces;i = j)
10078 surface = texturesurfacelist[i];
10080 if (surface->num_triangles > MAXBATCHTRIANGLES)
10082 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);
10085 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10086 batchtriangles = surface->num_triangles;
10087 firstvertex = surface->num_firstvertex;
10088 endvertex = surface->num_firstvertex + surface->num_vertices;
10089 for (;j < texturenumsurfaces;j++)
10091 surface2 = texturesurfacelist[j];
10092 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10094 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10095 batchtriangles += surface2->num_triangles;
10096 firstvertex = min(firstvertex, surface2->num_firstvertex);
10097 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10099 surface2 = texturesurfacelist[j-1];
10100 numvertices = endvertex - firstvertex;
10101 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10104 else if (r_batchmode.integer == 1)
10106 for (i = 0;i < texturenumsurfaces;i = j)
10108 surface = texturesurfacelist[i];
10109 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10110 if (texturesurfacelist[j] != surface2)
10112 surface2 = texturesurfacelist[j-1];
10113 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10114 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10115 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10120 for (i = 0;i < texturenumsurfaces;i++)
10122 surface = texturesurfacelist[i];
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);
10128 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10130 switch(vid.renderpath)
10132 case RENDERPATH_CGGL:
10134 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10135 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10138 case RENDERPATH_GL20:
10139 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10140 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10142 case RENDERPATH_GL13:
10143 case RENDERPATH_GL11:
10144 R_Mesh_TexBind(0, surface->lightmaptexture);
10149 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10151 // pick the closest matching water plane and bind textures
10152 int planeindex, vertexindex;
10156 r_waterstate_waterplane_t *p, *bestp;
10159 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10162 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10164 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10165 d += fabs(PlaneDiff(vert, &p->plane));
10167 if (bestd > d || !bestp)
10173 switch(vid.renderpath)
10175 case RENDERPATH_CGGL:
10177 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10178 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10181 case RENDERPATH_GL20:
10182 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10183 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10185 case RENDERPATH_GL13:
10186 case RENDERPATH_GL11:
10191 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10194 const msurface_t *surface;
10195 if (r_waterstate.renderingscene)
10197 for (i = 0;i < texturenumsurfaces;i++)
10199 surface = texturesurfacelist[i];
10200 RSurf_BindLightmapForSurface(surface);
10201 RSurf_BindReflectionForSurface(surface);
10202 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10206 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10210 const msurface_t *surface = texturesurfacelist[0];
10211 const msurface_t *surface2;
10216 if (texturenumsurfaces == 1)
10218 RSurf_BindLightmapForSurface(surface);
10219 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);
10221 else if (r_batchmode.integer == 2)
10223 #define MAXBATCHTRIANGLES 4096
10224 int batchtriangles = 0;
10225 static int batchelements[MAXBATCHTRIANGLES*3];
10226 for (i = 0;i < texturenumsurfaces;i = j)
10228 surface = texturesurfacelist[i];
10229 RSurf_BindLightmapForSurface(surface);
10231 if (surface->num_triangles > MAXBATCHTRIANGLES)
10233 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10236 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10237 batchtriangles = surface->num_triangles;
10238 firstvertex = surface->num_firstvertex;
10239 endvertex = surface->num_firstvertex + surface->num_vertices;
10240 for (;j < texturenumsurfaces;j++)
10242 surface2 = texturesurfacelist[j];
10243 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10245 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10246 batchtriangles += surface2->num_triangles;
10247 firstvertex = min(firstvertex, surface2->num_firstvertex);
10248 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10250 surface2 = texturesurfacelist[j-1];
10251 numvertices = endvertex - firstvertex;
10252 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10255 else if (r_batchmode.integer == 1)
10258 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10259 for (i = 0;i < texturenumsurfaces;i = j)
10261 surface = texturesurfacelist[i];
10262 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10263 if (texturesurfacelist[j] != surface2)
10265 Con_Printf(" %i", j - i);
10268 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10270 for (i = 0;i < texturenumsurfaces;i = j)
10272 surface = texturesurfacelist[i];
10273 RSurf_BindLightmapForSurface(surface);
10274 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10275 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10278 Con_Printf(" %i", j - i);
10280 surface2 = texturesurfacelist[j-1];
10281 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10282 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10283 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10291 for (i = 0;i < texturenumsurfaces;i++)
10293 surface = texturesurfacelist[i];
10294 RSurf_BindLightmapForSurface(surface);
10295 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);
10300 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10303 int texturesurfaceindex;
10304 if (r_showsurfaces.integer == 2)
10306 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10308 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10309 for (j = 0;j < surface->num_triangles;j++)
10311 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10312 GL_Color(f, f, f, 1);
10313 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10319 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10321 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10322 int k = (int)(((size_t)surface) / sizeof(msurface_t));
10323 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);
10324 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);
10329 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10331 int texturesurfaceindex;
10335 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10337 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10338 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)
10346 rsurface.lightmapcolor4f = rsurface.array_color4f;
10347 rsurface.lightmapcolor4f_bufferobject = 0;
10348 rsurface.lightmapcolor4f_bufferoffset = 0;
10351 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10353 int texturesurfaceindex;
10359 if (rsurface.lightmapcolor4f)
10361 // generate color arrays for the surfaces in this list
10362 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10364 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10365 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)
10367 f = RSurf_FogVertex(v);
10377 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10379 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10380 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)
10382 f = RSurf_FogVertex(v);
10390 rsurface.lightmapcolor4f = rsurface.array_color4f;
10391 rsurface.lightmapcolor4f_bufferobject = 0;
10392 rsurface.lightmapcolor4f_bufferoffset = 0;
10395 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10397 int texturesurfaceindex;
10403 if (!rsurface.lightmapcolor4f)
10405 // generate color arrays for the surfaces in this list
10406 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10408 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10409 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)
10411 f = RSurf_FogVertex(v);
10412 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10413 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10414 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10418 rsurface.lightmapcolor4f = rsurface.array_color4f;
10419 rsurface.lightmapcolor4f_bufferobject = 0;
10420 rsurface.lightmapcolor4f_bufferoffset = 0;
10423 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10425 int texturesurfaceindex;
10429 if (!rsurface.lightmapcolor4f)
10431 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10433 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10434 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)
10442 rsurface.lightmapcolor4f = rsurface.array_color4f;
10443 rsurface.lightmapcolor4f_bufferobject = 0;
10444 rsurface.lightmapcolor4f_bufferoffset = 0;
10447 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10449 int texturesurfaceindex;
10453 if (!rsurface.lightmapcolor4f)
10455 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10457 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10458 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)
10460 c2[0] = c[0] + r_refdef.scene.ambient;
10461 c2[1] = c[1] + r_refdef.scene.ambient;
10462 c2[2] = c[2] + r_refdef.scene.ambient;
10466 rsurface.lightmapcolor4f = rsurface.array_color4f;
10467 rsurface.lightmapcolor4f_bufferobject = 0;
10468 rsurface.lightmapcolor4f_bufferoffset = 0;
10471 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10474 rsurface.lightmapcolor4f = NULL;
10475 rsurface.lightmapcolor4f_bufferobject = 0;
10476 rsurface.lightmapcolor4f_bufferoffset = 0;
10477 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10478 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10479 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10480 GL_Color(r, g, b, a);
10481 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10484 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10486 // TODO: optimize applyfog && applycolor case
10487 // just apply fog if necessary, and tint the fog color array if necessary
10488 rsurface.lightmapcolor4f = NULL;
10489 rsurface.lightmapcolor4f_bufferobject = 0;
10490 rsurface.lightmapcolor4f_bufferoffset = 0;
10491 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10492 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10493 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10494 GL_Color(r, g, b, a);
10495 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10498 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10500 int texturesurfaceindex;
10504 if (texturesurfacelist[0]->lightmapinfo)
10506 // generate color arrays for the surfaces in this list
10507 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10509 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10510 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10512 if (surface->lightmapinfo->samples)
10514 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10515 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10516 VectorScale(lm, scale, c);
10517 if (surface->lightmapinfo->styles[1] != 255)
10519 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10521 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10522 VectorMA(c, scale, lm, c);
10523 if (surface->lightmapinfo->styles[2] != 255)
10526 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10527 VectorMA(c, scale, lm, c);
10528 if (surface->lightmapinfo->styles[3] != 255)
10531 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10532 VectorMA(c, scale, lm, c);
10542 rsurface.lightmapcolor4f = rsurface.array_color4f;
10543 rsurface.lightmapcolor4f_bufferobject = 0;
10544 rsurface.lightmapcolor4f_bufferoffset = 0;
10548 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10549 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10550 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10552 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10553 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10554 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10555 GL_Color(r, g, b, a);
10556 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10559 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10561 int texturesurfaceindex;
10568 vec3_t ambientcolor;
10569 vec3_t diffusecolor;
10573 VectorCopy(rsurface.modellight_lightdir, lightdir);
10574 f = 0.5f * r_refdef.lightmapintensity;
10575 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10576 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10577 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10578 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10579 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10580 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10582 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10584 // generate color arrays for the surfaces in this list
10585 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10587 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10588 int numverts = surface->num_vertices;
10589 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10590 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10591 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10592 // q3-style directional shading
10593 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10595 if ((f = DotProduct(n, lightdir)) > 0)
10596 VectorMA(ambientcolor, f, diffusecolor, c);
10598 VectorCopy(ambientcolor, c);
10606 rsurface.lightmapcolor4f = rsurface.array_color4f;
10607 rsurface.lightmapcolor4f_bufferobject = 0;
10608 rsurface.lightmapcolor4f_bufferoffset = 0;
10609 *applycolor = false;
10613 *r = ambientcolor[0];
10614 *g = ambientcolor[1];
10615 *b = ambientcolor[2];
10616 rsurface.lightmapcolor4f = NULL;
10617 rsurface.lightmapcolor4f_bufferobject = 0;
10618 rsurface.lightmapcolor4f_bufferoffset = 0;
10622 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10624 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10625 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10626 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10627 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10628 GL_Color(r, g, b, a);
10629 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10632 void RSurf_SetupDepthAndCulling(void)
10634 // submodels are biased to avoid z-fighting with world surfaces that they
10635 // may be exactly overlapping (avoids z-fighting artifacts on certain
10636 // doors and things in Quake maps)
10637 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10638 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10639 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10640 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10643 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10645 // transparent sky would be ridiculous
10646 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10648 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10649 skyrenderlater = true;
10650 RSurf_SetupDepthAndCulling();
10651 GL_DepthMask(true);
10652 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10653 // skymasking on them, and Quake3 never did sky masking (unlike
10654 // software Quake and software Quake2), so disable the sky masking
10655 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10656 // and skymasking also looks very bad when noclipping outside the
10657 // level, so don't use it then either.
10658 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10660 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10661 R_Mesh_ColorPointer(NULL, 0, 0);
10662 R_Mesh_ResetTextureState();
10663 if (skyrendermasked)
10665 R_SetupShader_DepthOrShadow();
10666 // depth-only (masking)
10667 GL_ColorMask(0,0,0,0);
10668 // just to make sure that braindead drivers don't draw
10669 // anything despite that colormask...
10670 GL_BlendFunc(GL_ZERO, GL_ONE);
10674 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10676 GL_BlendFunc(GL_ONE, GL_ZERO);
10678 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10679 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10680 if (skyrendermasked)
10681 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10683 R_Mesh_ResetTextureState();
10684 GL_Color(1, 1, 1, 1);
10687 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10688 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10689 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10691 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10693 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10696 // render screenspace normalmap to texture
10697 GL_DepthMask(true);
10698 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10699 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10701 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10703 // render water or distortion background, then blend surface on top
10704 GL_DepthMask(true);
10705 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10706 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10707 GL_DepthMask(false);
10708 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10709 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10710 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10712 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10716 // render surface normally
10717 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10718 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10719 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10720 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10721 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10722 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10724 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10728 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10730 // OpenGL 1.3 path - anything not completely ancient
10731 int texturesurfaceindex;
10732 qboolean applycolor;
10735 const texturelayer_t *layer;
10736 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10738 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10741 int layertexrgbscale;
10742 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10744 if (layerindex == 0)
10745 GL_AlphaTest(true);
10748 GL_AlphaTest(false);
10749 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10752 GL_DepthMask(layer->depthmask && writedepth);
10753 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10754 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10756 layertexrgbscale = 4;
10757 VectorScale(layer->color, 0.25f, layercolor);
10759 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10761 layertexrgbscale = 2;
10762 VectorScale(layer->color, 0.5f, layercolor);
10766 layertexrgbscale = 1;
10767 VectorScale(layer->color, 1.0f, layercolor);
10769 layercolor[3] = layer->color[3];
10770 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10771 R_Mesh_ColorPointer(NULL, 0, 0);
10772 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10773 switch (layer->type)
10775 case TEXTURELAYERTYPE_LITTEXTURE:
10776 // single-pass lightmapped texture with 2x rgbscale
10777 R_Mesh_TexBind(0, r_texture_white);
10778 R_Mesh_TexMatrix(0, NULL);
10779 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10780 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10781 R_Mesh_TexBind(1, layer->texture);
10782 R_Mesh_TexMatrix(1, &layer->texmatrix);
10783 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10784 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10785 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10786 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10787 else if (rsurface.uselightmaptexture)
10788 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10790 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10792 case TEXTURELAYERTYPE_TEXTURE:
10793 // singletexture unlit texture with transparency support
10794 R_Mesh_TexBind(0, layer->texture);
10795 R_Mesh_TexMatrix(0, &layer->texmatrix);
10796 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10797 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10798 R_Mesh_TexBind(1, 0);
10799 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10800 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10802 case TEXTURELAYERTYPE_FOG:
10803 // singletexture fogging
10804 if (layer->texture)
10806 R_Mesh_TexBind(0, layer->texture);
10807 R_Mesh_TexMatrix(0, &layer->texmatrix);
10808 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10809 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10813 R_Mesh_TexBind(0, 0);
10814 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10816 R_Mesh_TexBind(1, 0);
10817 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10818 // generate a color array for the fog pass
10819 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10820 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10826 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10827 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)
10829 f = 1 - RSurf_FogVertex(v);
10830 c[0] = layercolor[0];
10831 c[1] = layercolor[1];
10832 c[2] = layercolor[2];
10833 c[3] = f * layercolor[3];
10836 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10839 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10843 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10845 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10846 GL_AlphaTest(false);
10850 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10852 // OpenGL 1.1 - crusty old voodoo path
10853 int texturesurfaceindex;
10856 const texturelayer_t *layer;
10857 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10859 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10861 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10863 if (layerindex == 0)
10864 GL_AlphaTest(true);
10867 GL_AlphaTest(false);
10868 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10871 GL_DepthMask(layer->depthmask && writedepth);
10872 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10873 R_Mesh_ColorPointer(NULL, 0, 0);
10874 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10875 switch (layer->type)
10877 case TEXTURELAYERTYPE_LITTEXTURE:
10878 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10880 // two-pass lit texture with 2x rgbscale
10881 // first the lightmap pass
10882 R_Mesh_TexBind(0, r_texture_white);
10883 R_Mesh_TexMatrix(0, NULL);
10884 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10885 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10886 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10887 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10888 else if (rsurface.uselightmaptexture)
10889 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10891 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10892 // then apply the texture to it
10893 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10894 R_Mesh_TexBind(0, layer->texture);
10895 R_Mesh_TexMatrix(0, &layer->texmatrix);
10896 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10897 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10898 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);
10902 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10903 R_Mesh_TexBind(0, layer->texture);
10904 R_Mesh_TexMatrix(0, &layer->texmatrix);
10905 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10906 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10907 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10908 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);
10910 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);
10913 case TEXTURELAYERTYPE_TEXTURE:
10914 // singletexture unlit texture with transparency support
10915 R_Mesh_TexBind(0, layer->texture);
10916 R_Mesh_TexMatrix(0, &layer->texmatrix);
10917 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10918 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10919 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);
10921 case TEXTURELAYERTYPE_FOG:
10922 // singletexture fogging
10923 if (layer->texture)
10925 R_Mesh_TexBind(0, layer->texture);
10926 R_Mesh_TexMatrix(0, &layer->texmatrix);
10927 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10928 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10932 R_Mesh_TexBind(0, 0);
10933 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10935 // generate a color array for the fog pass
10936 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10937 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10943 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10944 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)
10946 f = 1 - RSurf_FogVertex(v);
10947 c[0] = layer->color[0];
10948 c[1] = layer->color[1];
10949 c[2] = layer->color[2];
10950 c[3] = f * layer->color[3];
10953 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10956 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10960 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10962 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10963 GL_AlphaTest(false);
10967 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10971 GL_AlphaTest(false);
10972 R_Mesh_ColorPointer(NULL, 0, 0);
10973 R_Mesh_ResetTextureState();
10974 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10976 if(rsurface.texture && rsurface.texture->currentskinframe)
10978 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10979 c[3] *= rsurface.texture->currentalpha;
10989 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10991 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10992 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10993 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10996 // brighten it up (as texture value 127 means "unlit")
10997 c[0] *= 2 * r_refdef.view.colorscale;
10998 c[1] *= 2 * r_refdef.view.colorscale;
10999 c[2] *= 2 * r_refdef.view.colorscale;
11001 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11002 c[3] *= r_wateralpha.value;
11004 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11006 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11007 GL_DepthMask(false);
11009 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11011 GL_BlendFunc(GL_ONE, GL_ONE);
11012 GL_DepthMask(false);
11014 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11016 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11017 GL_DepthMask(false);
11019 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11021 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11022 GL_DepthMask(false);
11026 GL_BlendFunc(GL_ONE, GL_ZERO);
11027 GL_DepthMask(writedepth);
11030 rsurface.lightmapcolor4f = NULL;
11032 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11034 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11036 rsurface.lightmapcolor4f = NULL;
11037 rsurface.lightmapcolor4f_bufferobject = 0;
11038 rsurface.lightmapcolor4f_bufferoffset = 0;
11040 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11042 qboolean applycolor = true;
11045 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11047 r_refdef.lightmapintensity = 1;
11048 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11049 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11053 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11055 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11056 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11057 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11060 if(!rsurface.lightmapcolor4f)
11061 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11063 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11064 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11065 if(r_refdef.fogenabled)
11066 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11068 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11069 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11072 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11075 RSurf_SetupDepthAndCulling();
11076 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11078 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11081 switch (vid.renderpath)
11083 case RENDERPATH_GL20:
11084 case RENDERPATH_CGGL:
11085 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11087 case RENDERPATH_GL13:
11088 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11090 case RENDERPATH_GL11:
11091 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11097 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11100 RSurf_SetupDepthAndCulling();
11101 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11103 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11106 switch (vid.renderpath)
11108 case RENDERPATH_GL20:
11109 case RENDERPATH_CGGL:
11110 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11112 case RENDERPATH_GL13:
11113 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11115 case RENDERPATH_GL11:
11116 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11122 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11125 int texturenumsurfaces, endsurface;
11126 texture_t *texture;
11127 const msurface_t *surface;
11128 const msurface_t *texturesurfacelist[256];
11130 // if the model is static it doesn't matter what value we give for
11131 // wantnormals and wanttangents, so this logic uses only rules applicable
11132 // to a model, knowing that they are meaningless otherwise
11133 if (ent == r_refdef.scene.worldentity)
11134 RSurf_ActiveWorldEntity();
11135 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11136 RSurf_ActiveModelEntity(ent, false, false, false);
11139 switch (vid.renderpath)
11141 case RENDERPATH_GL20:
11142 case RENDERPATH_CGGL:
11143 RSurf_ActiveModelEntity(ent, true, true, false);
11145 case RENDERPATH_GL13:
11146 case RENDERPATH_GL11:
11147 RSurf_ActiveModelEntity(ent, true, false, false);
11152 if (r_transparentdepthmasking.integer)
11154 qboolean setup = false;
11155 for (i = 0;i < numsurfaces;i = j)
11158 surface = rsurface.modelsurfaces + surfacelist[i];
11159 texture = surface->texture;
11160 rsurface.texture = R_GetCurrentTexture(texture);
11161 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11162 // scan ahead until we find a different texture
11163 endsurface = min(i + 1024, numsurfaces);
11164 texturenumsurfaces = 0;
11165 texturesurfacelist[texturenumsurfaces++] = surface;
11166 for (;j < endsurface;j++)
11168 surface = rsurface.modelsurfaces + surfacelist[j];
11169 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11171 texturesurfacelist[texturenumsurfaces++] = surface;
11173 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11175 // render the range of surfaces as depth
11179 GL_ColorMask(0,0,0,0);
11181 GL_DepthTest(true);
11182 GL_BlendFunc(GL_ONE, GL_ZERO);
11183 GL_DepthMask(true);
11184 GL_AlphaTest(false);
11185 R_Mesh_ColorPointer(NULL, 0, 0);
11186 R_Mesh_ResetTextureState();
11187 R_SetupShader_DepthOrShadow();
11189 RSurf_SetupDepthAndCulling();
11190 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11191 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11194 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11197 for (i = 0;i < numsurfaces;i = j)
11200 surface = rsurface.modelsurfaces + surfacelist[i];
11201 texture = surface->texture;
11202 rsurface.texture = R_GetCurrentTexture(texture);
11203 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11204 // scan ahead until we find a different texture
11205 endsurface = min(i + 1024, numsurfaces);
11206 texturenumsurfaces = 0;
11207 texturesurfacelist[texturenumsurfaces++] = surface;
11208 for (;j < endsurface;j++)
11210 surface = rsurface.modelsurfaces + surfacelist[j];
11211 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11213 texturesurfacelist[texturenumsurfaces++] = surface;
11215 // render the range of surfaces
11216 if (ent == r_refdef.scene.worldentity)
11217 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11219 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11221 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11222 GL_AlphaTest(false);
11225 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11227 // transparent surfaces get pushed off into the transparent queue
11228 int surfacelistindex;
11229 const msurface_t *surface;
11230 vec3_t tempcenter, center;
11231 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11233 surface = texturesurfacelist[surfacelistindex];
11234 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11235 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11236 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11237 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11238 if (queueentity->transparent_offset) // transparent offset
11240 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11241 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11242 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11244 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11248 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11250 const entity_render_t *queueentity = r_refdef.scene.worldentity;
11254 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11256 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11258 RSurf_SetupDepthAndCulling();
11259 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11260 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11264 if (!rsurface.texture->currentnumlayers)
11266 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11267 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11269 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11271 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11273 RSurf_SetupDepthAndCulling();
11274 GL_AlphaTest(false);
11275 R_Mesh_ColorPointer(NULL, 0, 0);
11276 R_Mesh_ResetTextureState();
11277 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11278 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11279 GL_DepthMask(true);
11280 GL_BlendFunc(GL_ONE, GL_ZERO);
11281 GL_Color(0, 0, 0, 1);
11282 GL_DepthTest(writedepth);
11283 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11285 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11287 RSurf_SetupDepthAndCulling();
11288 GL_AlphaTest(false);
11289 R_Mesh_ColorPointer(NULL, 0, 0);
11290 R_Mesh_ResetTextureState();
11291 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11292 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11293 GL_DepthMask(true);
11294 GL_BlendFunc(GL_ONE, GL_ZERO);
11295 GL_DepthTest(true);
11296 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11298 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11299 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11300 else if (!rsurface.texture->currentnumlayers)
11302 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11304 // in the deferred case, transparent surfaces were queued during prepass
11305 if (!r_shadow_usingdeferredprepass)
11306 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11310 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11311 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11316 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11319 texture_t *texture;
11320 // break the surface list down into batches by texture and use of lightmapping
11321 for (i = 0;i < numsurfaces;i = j)
11324 // texture is the base texture pointer, rsurface.texture is the
11325 // current frame/skin the texture is directing us to use (for example
11326 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11327 // use skin 1 instead)
11328 texture = surfacelist[i]->texture;
11329 rsurface.texture = R_GetCurrentTexture(texture);
11330 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11331 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11333 // if this texture is not the kind we want, skip ahead to the next one
11334 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11338 // simply scan ahead until we find a different texture or lightmap state
11339 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11341 // render the range of surfaces
11342 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11346 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11351 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11353 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11355 RSurf_SetupDepthAndCulling();
11356 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11357 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11361 if (!rsurface.texture->currentnumlayers)
11363 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11364 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11366 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11368 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11370 RSurf_SetupDepthAndCulling();
11371 GL_AlphaTest(false);
11372 R_Mesh_ColorPointer(NULL, 0, 0);
11373 R_Mesh_ResetTextureState();
11374 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11375 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11376 GL_DepthMask(true);
11377 GL_BlendFunc(GL_ONE, GL_ZERO);
11378 GL_Color(0, 0, 0, 1);
11379 GL_DepthTest(writedepth);
11380 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11382 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11384 RSurf_SetupDepthAndCulling();
11385 GL_AlphaTest(false);
11386 R_Mesh_ColorPointer(NULL, 0, 0);
11387 R_Mesh_ResetTextureState();
11388 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11389 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11390 GL_DepthMask(true);
11391 GL_BlendFunc(GL_ONE, GL_ZERO);
11392 GL_DepthTest(true);
11393 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11395 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11396 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11397 else if (!rsurface.texture->currentnumlayers)
11399 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11401 // in the deferred case, transparent surfaces were queued during prepass
11402 if (!r_shadow_usingdeferredprepass)
11403 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11407 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11408 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11413 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11416 texture_t *texture;
11417 // break the surface list down into batches by texture and use of lightmapping
11418 for (i = 0;i < numsurfaces;i = j)
11421 // texture is the base texture pointer, rsurface.texture is the
11422 // current frame/skin the texture is directing us to use (for example
11423 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11424 // use skin 1 instead)
11425 texture = surfacelist[i]->texture;
11426 rsurface.texture = R_GetCurrentTexture(texture);
11427 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11428 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11430 // if this texture is not the kind we want, skip ahead to the next one
11431 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11435 // simply scan ahead until we find a different texture or lightmap state
11436 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11438 // render the range of surfaces
11439 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11443 float locboxvertex3f[6*4*3] =
11445 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11446 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11447 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11448 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11449 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11450 1,0,0, 0,0,0, 0,1,0, 1,1,0
11453 unsigned short locboxelements[6*2*3] =
11458 12,13,14, 12,14,15,
11459 16,17,18, 16,18,19,
11463 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11466 cl_locnode_t *loc = (cl_locnode_t *)ent;
11468 float vertex3f[6*4*3];
11470 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11471 GL_DepthMask(false);
11472 GL_DepthRange(0, 1);
11473 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11474 GL_DepthTest(true);
11475 GL_CullFace(GL_NONE);
11476 R_EntityMatrix(&identitymatrix);
11478 R_Mesh_VertexPointer(vertex3f, 0, 0);
11479 R_Mesh_ColorPointer(NULL, 0, 0);
11480 R_Mesh_ResetTextureState();
11481 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11483 i = surfacelist[0];
11484 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11485 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11486 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11487 surfacelist[0] < 0 ? 0.5f : 0.125f);
11489 if (VectorCompare(loc->mins, loc->maxs))
11491 VectorSet(size, 2, 2, 2);
11492 VectorMA(loc->mins, -0.5f, size, mins);
11496 VectorCopy(loc->mins, mins);
11497 VectorSubtract(loc->maxs, loc->mins, size);
11500 for (i = 0;i < 6*4*3;)
11501 for (j = 0;j < 3;j++, i++)
11502 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11504 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11507 void R_DrawLocs(void)
11510 cl_locnode_t *loc, *nearestloc;
11512 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11513 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11515 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11516 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11520 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11522 if (decalsystem->decals)
11523 Mem_Free(decalsystem->decals);
11524 memset(decalsystem, 0, sizeof(*decalsystem));
11527 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)
11530 tridecal_t *decals;
11533 // expand or initialize the system
11534 if (decalsystem->maxdecals <= decalsystem->numdecals)
11536 decalsystem_t old = *decalsystem;
11537 qboolean useshortelements;
11538 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11539 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11540 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)));
11541 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11542 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11543 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11544 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11545 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11546 if (decalsystem->numdecals)
11547 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11549 Mem_Free(old.decals);
11550 for (i = 0;i < decalsystem->maxdecals*3;i++)
11551 decalsystem->element3i[i] = i;
11552 if (useshortelements)
11553 for (i = 0;i < decalsystem->maxdecals*3;i++)
11554 decalsystem->element3s[i] = i;
11557 // grab a decal and search for another free slot for the next one
11558 decals = decalsystem->decals;
11559 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11560 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11562 decalsystem->freedecal = i;
11563 if (decalsystem->numdecals <= i)
11564 decalsystem->numdecals = i + 1;
11566 // initialize the decal
11568 decal->triangleindex = triangleindex;
11569 decal->surfaceindex = surfaceindex;
11570 decal->decalsequence = decalsequence;
11571 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11572 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11573 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11574 decal->color4ub[0][3] = 255;
11575 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11576 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11577 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11578 decal->color4ub[1][3] = 255;
11579 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11580 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11581 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11582 decal->color4ub[2][3] = 255;
11583 decal->vertex3f[0][0] = v0[0];
11584 decal->vertex3f[0][1] = v0[1];
11585 decal->vertex3f[0][2] = v0[2];
11586 decal->vertex3f[1][0] = v1[0];
11587 decal->vertex3f[1][1] = v1[1];
11588 decal->vertex3f[1][2] = v1[2];
11589 decal->vertex3f[2][0] = v2[0];
11590 decal->vertex3f[2][1] = v2[1];
11591 decal->vertex3f[2][2] = v2[2];
11592 decal->texcoord2f[0][0] = t0[0];
11593 decal->texcoord2f[0][1] = t0[1];
11594 decal->texcoord2f[1][0] = t1[0];
11595 decal->texcoord2f[1][1] = t1[1];
11596 decal->texcoord2f[2][0] = t2[0];
11597 decal->texcoord2f[2][1] = t2[1];
11600 extern cvar_t cl_decals_bias;
11601 extern cvar_t cl_decals_models;
11602 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11603 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)
11605 matrix4x4_t projection;
11606 decalsystem_t *decalsystem;
11609 const float *vertex3f;
11610 const msurface_t *surface;
11611 const msurface_t *surfaces;
11612 const int *surfacelist;
11613 const texture_t *texture;
11615 int numsurfacelist;
11616 int surfacelistindex;
11623 float localorigin[3];
11624 float localnormal[3];
11625 float localmins[3];
11626 float localmaxs[3];
11632 float planes[6][4];
11634 float points[2][9][3];
11638 decalsystem = &ent->decalsystem;
11639 model = ent->model;
11640 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11642 R_DecalSystem_Reset(&ent->decalsystem);
11646 if (!model->brush.data_nodes && !cl_decals_models.integer)
11648 if (decalsystem->model)
11649 R_DecalSystem_Reset(decalsystem);
11653 if (decalsystem->model != model)
11654 R_DecalSystem_Reset(decalsystem);
11655 decalsystem->model = model;
11657 RSurf_ActiveModelEntity(ent, false, false, false);
11659 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11660 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11661 VectorNormalize(localnormal);
11662 localsize = worldsize*rsurface.inversematrixscale;
11663 localmins[0] = localorigin[0] - localsize;
11664 localmins[1] = localorigin[1] - localsize;
11665 localmins[2] = localorigin[2] - localsize;
11666 localmaxs[0] = localorigin[0] + localsize;
11667 localmaxs[1] = localorigin[1] + localsize;
11668 localmaxs[2] = localorigin[2] + localsize;
11670 //VectorCopy(localnormal, planes[4]);
11671 //VectorVectors(planes[4], planes[2], planes[0]);
11672 AnglesFromVectors(angles, localnormal, NULL, false);
11673 AngleVectors(angles, planes[0], planes[2], planes[4]);
11674 VectorNegate(planes[0], planes[1]);
11675 VectorNegate(planes[2], planes[3]);
11676 VectorNegate(planes[4], planes[5]);
11677 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11678 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11679 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11680 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11681 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11682 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11687 matrix4x4_t forwardprojection;
11688 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11689 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11694 float projectionvector[4][3];
11695 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11696 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11697 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11698 projectionvector[0][0] = planes[0][0] * ilocalsize;
11699 projectionvector[0][1] = planes[1][0] * ilocalsize;
11700 projectionvector[0][2] = planes[2][0] * ilocalsize;
11701 projectionvector[1][0] = planes[0][1] * ilocalsize;
11702 projectionvector[1][1] = planes[1][1] * ilocalsize;
11703 projectionvector[1][2] = planes[2][1] * ilocalsize;
11704 projectionvector[2][0] = planes[0][2] * ilocalsize;
11705 projectionvector[2][1] = planes[1][2] * ilocalsize;
11706 projectionvector[2][2] = planes[2][2] * ilocalsize;
11707 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11708 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11709 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11710 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11714 dynamic = model->surfmesh.isanimated;
11715 vertex3f = rsurface.modelvertex3f;
11716 numsurfacelist = model->nummodelsurfaces;
11717 surfacelist = model->sortedmodelsurfaces;
11718 surfaces = model->data_surfaces;
11719 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11721 surfaceindex = surfacelist[surfacelistindex];
11722 surface = surfaces + surfaceindex;
11723 // check cull box first because it rejects more than any other check
11724 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11726 // skip transparent surfaces
11727 texture = surface->texture;
11728 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11730 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11732 numtriangles = surface->num_triangles;
11733 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11735 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11737 index = 3*e[cornerindex];
11738 VectorCopy(vertex3f + index, v[cornerindex]);
11741 //TriangleNormal(v[0], v[1], v[2], normal);
11742 //if (DotProduct(normal, localnormal) < 0.0f)
11744 // clip by each of the box planes formed from the projection matrix
11745 // if anything survives, we emit the decal
11746 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]);
11749 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]);
11752 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]);
11755 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]);
11758 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]);
11761 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]);
11764 // some part of the triangle survived, so we have to accept it...
11767 // dynamic always uses the original triangle
11769 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11771 index = 3*e[cornerindex];
11772 VectorCopy(vertex3f + index, v[cornerindex]);
11775 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11777 // convert vertex positions to texcoords
11778 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11779 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11780 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11781 // calculate distance fade from the projection origin
11782 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11783 f = bound(0.0f, f, 1.0f);
11784 c[cornerindex][0] = r * f;
11785 c[cornerindex][1] = g * f;
11786 c[cornerindex][2] = b * f;
11787 c[cornerindex][3] = 1.0f;
11788 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11791 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);
11793 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11794 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);
11799 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11800 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)
11802 int renderentityindex;
11803 float worldmins[3];
11804 float worldmaxs[3];
11805 entity_render_t *ent;
11807 if (!cl_decals_newsystem.integer)
11810 worldmins[0] = worldorigin[0] - worldsize;
11811 worldmins[1] = worldorigin[1] - worldsize;
11812 worldmins[2] = worldorigin[2] - worldsize;
11813 worldmaxs[0] = worldorigin[0] + worldsize;
11814 worldmaxs[1] = worldorigin[1] + worldsize;
11815 worldmaxs[2] = worldorigin[2] + worldsize;
11817 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11819 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11821 ent = r_refdef.scene.entities[renderentityindex];
11822 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11825 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11829 typedef struct r_decalsystem_splatqueue_s
11831 vec3_t worldorigin;
11832 vec3_t worldnormal;
11838 r_decalsystem_splatqueue_t;
11840 int r_decalsystem_numqueued = 0;
11841 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11843 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)
11845 r_decalsystem_splatqueue_t *queue;
11847 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11850 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11851 VectorCopy(worldorigin, queue->worldorigin);
11852 VectorCopy(worldnormal, queue->worldnormal);
11853 Vector4Set(queue->color, r, g, b, a);
11854 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11855 queue->worldsize = worldsize;
11856 queue->decalsequence = cl.decalsequence++;
11859 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11862 r_decalsystem_splatqueue_t *queue;
11864 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11865 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);
11866 r_decalsystem_numqueued = 0;
11869 extern cvar_t cl_decals_max;
11870 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11873 decalsystem_t *decalsystem = &ent->decalsystem;
11880 if (!decalsystem->numdecals)
11883 if (r_showsurfaces.integer)
11886 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11888 R_DecalSystem_Reset(decalsystem);
11892 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11893 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11895 if (decalsystem->lastupdatetime)
11896 frametime = (cl.time - decalsystem->lastupdatetime);
11899 decalsystem->lastupdatetime = cl.time;
11900 decal = decalsystem->decals;
11901 numdecals = decalsystem->numdecals;
11903 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11905 if (decal->color4ub[0][3])
11907 decal->lived += frametime;
11908 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11910 memset(decal, 0, sizeof(*decal));
11911 if (decalsystem->freedecal > i)
11912 decalsystem->freedecal = i;
11916 decal = decalsystem->decals;
11917 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11920 // collapse the array by shuffling the tail decals into the gaps
11923 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11924 decalsystem->freedecal++;
11925 if (decalsystem->freedecal == numdecals)
11927 decal[decalsystem->freedecal] = decal[--numdecals];
11930 decalsystem->numdecals = numdecals;
11932 if (numdecals <= 0)
11934 // if there are no decals left, reset decalsystem
11935 R_DecalSystem_Reset(decalsystem);
11939 extern skinframe_t *decalskinframe;
11940 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11943 decalsystem_t *decalsystem = &ent->decalsystem;
11952 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11955 numdecals = decalsystem->numdecals;
11959 if (r_showsurfaces.integer)
11962 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11964 R_DecalSystem_Reset(decalsystem);
11968 // if the model is static it doesn't matter what value we give for
11969 // wantnormals and wanttangents, so this logic uses only rules applicable
11970 // to a model, knowing that they are meaningless otherwise
11971 if (ent == r_refdef.scene.worldentity)
11972 RSurf_ActiveWorldEntity();
11974 RSurf_ActiveModelEntity(ent, false, false, false);
11976 decalsystem->lastupdatetime = cl.time;
11977 decal = decalsystem->decals;
11979 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11981 // update vertex positions for animated models
11982 v3f = decalsystem->vertex3f;
11983 c4f = decalsystem->color4f;
11984 t2f = decalsystem->texcoord2f;
11985 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11987 if (!decal->color4ub[0][3])
11990 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11993 // update color values for fading decals
11994 if (decal->lived >= cl_decals_time.value)
11996 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11997 alpha *= (1.0f/255.0f);
12000 alpha = 1.0f/255.0f;
12002 c4f[ 0] = decal->color4ub[0][0] * alpha;
12003 c4f[ 1] = decal->color4ub[0][1] * alpha;
12004 c4f[ 2] = decal->color4ub[0][2] * alpha;
12006 c4f[ 4] = decal->color4ub[1][0] * alpha;
12007 c4f[ 5] = decal->color4ub[1][1] * alpha;
12008 c4f[ 6] = decal->color4ub[1][2] * alpha;
12010 c4f[ 8] = decal->color4ub[2][0] * alpha;
12011 c4f[ 9] = decal->color4ub[2][1] * alpha;
12012 c4f[10] = decal->color4ub[2][2] * alpha;
12015 t2f[0] = decal->texcoord2f[0][0];
12016 t2f[1] = decal->texcoord2f[0][1];
12017 t2f[2] = decal->texcoord2f[1][0];
12018 t2f[3] = decal->texcoord2f[1][1];
12019 t2f[4] = decal->texcoord2f[2][0];
12020 t2f[5] = decal->texcoord2f[2][1];
12022 // update vertex positions for animated models
12023 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12025 e = rsurface.modelelement3i + 3*decal->triangleindex;
12026 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12027 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12028 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12032 VectorCopy(decal->vertex3f[0], v3f);
12033 VectorCopy(decal->vertex3f[1], v3f + 3);
12034 VectorCopy(decal->vertex3f[2], v3f + 6);
12045 r_refdef.stats.drawndecals += numtris;
12047 if (r_refdef.fogenabled)
12049 switch(vid.renderpath)
12051 case RENDERPATH_GL20:
12052 case RENDERPATH_CGGL:
12053 case RENDERPATH_GL13:
12054 case RENDERPATH_GL11:
12055 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
12057 alpha = RSurf_FogVertex(v3f);
12066 // now render the decals all at once
12067 // (this assumes they all use one particle font texture!)
12068 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);
12069 R_Mesh_ResetTextureState();
12070 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12071 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12072 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12073 GL_DepthMask(false);
12074 GL_DepthRange(0, 1);
12075 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12076 GL_DepthTest(true);
12077 GL_CullFace(GL_NONE);
12078 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12079 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12080 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12084 static void R_DrawModelDecals(void)
12088 // fade faster when there are too many decals
12089 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12090 for (i = 0;i < r_refdef.scene.numentities;i++)
12091 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12093 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12094 for (i = 0;i < r_refdef.scene.numentities;i++)
12095 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12096 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12098 R_DecalSystem_ApplySplatEntitiesQueue();
12100 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12101 for (i = 0;i < r_refdef.scene.numentities;i++)
12102 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12104 r_refdef.stats.totaldecals += numdecals;
12106 if (r_showsurfaces.integer)
12109 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12111 for (i = 0;i < r_refdef.scene.numentities;i++)
12113 if (!r_refdef.viewcache.entityvisible[i])
12115 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12116 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12120 void R_DrawDebugModel(void)
12122 entity_render_t *ent = rsurface.entity;
12123 int i, j, k, l, flagsmask;
12125 const msurface_t *surface;
12126 dp_model_t *model = ent->model;
12129 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12131 R_Mesh_ColorPointer(NULL, 0, 0);
12132 R_Mesh_ResetTextureState();
12133 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12134 GL_DepthRange(0, 1);
12135 GL_DepthTest(!r_showdisabledepthtest.integer);
12136 GL_DepthMask(false);
12137 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12139 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
12141 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12142 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
12144 if (brush->colbrushf && brush->colbrushf->numtriangles)
12146 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12147 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);
12148 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12151 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
12153 if (surface->num_collisiontriangles)
12155 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
12156 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);
12157 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
12162 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12164 if (r_showtris.integer || r_shownormals.integer)
12166 if (r_showdisabledepthtest.integer)
12168 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12169 GL_DepthMask(false);
12173 GL_BlendFunc(GL_ONE, GL_ZERO);
12174 GL_DepthMask(true);
12176 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12178 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12180 rsurface.texture = R_GetCurrentTexture(surface->texture);
12181 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12183 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12184 if (r_showtris.value > 0)
12186 if (!rsurface.texture->currentlayers->depthmask)
12187 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12188 else if (ent == r_refdef.scene.worldentity)
12189 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12191 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12192 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12193 R_Mesh_ColorPointer(NULL, 0, 0);
12194 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12195 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12196 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12197 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);
12198 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12201 if (r_shownormals.value < 0)
12203 qglBegin(GL_LINES);
12204 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12206 VectorCopy(rsurface.vertex3f + l * 3, v);
12207 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12208 qglVertex3f(v[0], v[1], v[2]);
12209 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12210 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12211 qglVertex3f(v[0], v[1], v[2]);
12216 if (r_shownormals.value > 0)
12218 qglBegin(GL_LINES);
12219 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12221 VectorCopy(rsurface.vertex3f + l * 3, v);
12222 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12223 qglVertex3f(v[0], v[1], v[2]);
12224 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12225 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12226 qglVertex3f(v[0], v[1], v[2]);
12230 qglBegin(GL_LINES);
12231 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12233 VectorCopy(rsurface.vertex3f + l * 3, v);
12234 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12235 qglVertex3f(v[0], v[1], v[2]);
12236 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12237 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12238 qglVertex3f(v[0], v[1], v[2]);
12242 qglBegin(GL_LINES);
12243 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12245 VectorCopy(rsurface.vertex3f + l * 3, v);
12246 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12247 qglVertex3f(v[0], v[1], v[2]);
12248 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12249 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12250 qglVertex3f(v[0], v[1], v[2]);
12257 rsurface.texture = NULL;
12261 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12262 int r_maxsurfacelist = 0;
12263 const msurface_t **r_surfacelist = NULL;
12264 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12266 int i, j, endj, flagsmask;
12267 dp_model_t *model = r_refdef.scene.worldmodel;
12268 msurface_t *surfaces;
12269 unsigned char *update;
12270 int numsurfacelist = 0;
12274 if (r_maxsurfacelist < model->num_surfaces)
12276 r_maxsurfacelist = model->num_surfaces;
12278 Mem_Free((msurface_t**)r_surfacelist);
12279 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12282 RSurf_ActiveWorldEntity();
12284 surfaces = model->data_surfaces;
12285 update = model->brushq1.lightmapupdateflags;
12287 // update light styles on this submodel
12288 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12290 model_brush_lightstyleinfo_t *style;
12291 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12293 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12295 int *list = style->surfacelist;
12296 style->value = r_refdef.scene.lightstylevalue[style->style];
12297 for (j = 0;j < style->numsurfaces;j++)
12298 update[list[j]] = true;
12303 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12307 R_DrawDebugModel();
12308 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12312 rsurface.uselightmaptexture = false;
12313 rsurface.texture = NULL;
12314 rsurface.rtlight = NULL;
12315 numsurfacelist = 0;
12316 // add visible surfaces to draw list
12317 for (i = 0;i < model->nummodelsurfaces;i++)
12319 j = model->sortedmodelsurfaces[i];
12320 if (r_refdef.viewcache.world_surfacevisible[j])
12321 r_surfacelist[numsurfacelist++] = surfaces + j;
12323 // update lightmaps if needed
12324 if (model->brushq1.firstrender)
12326 model->brushq1.firstrender = false;
12327 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12329 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12333 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12334 if (r_refdef.viewcache.world_surfacevisible[j])
12336 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12338 // don't do anything if there were no surfaces
12339 if (!numsurfacelist)
12341 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12344 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12345 GL_AlphaTest(false);
12347 // add to stats if desired
12348 if (r_speeds.integer && !skysurfaces && !depthonly)
12350 r_refdef.stats.world_surfaces += numsurfacelist;
12351 for (j = 0;j < numsurfacelist;j++)
12352 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12355 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12358 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12360 int i, j, endj, flagsmask;
12361 dp_model_t *model = ent->model;
12362 msurface_t *surfaces;
12363 unsigned char *update;
12364 int numsurfacelist = 0;
12368 if (r_maxsurfacelist < model->num_surfaces)
12370 r_maxsurfacelist = model->num_surfaces;
12372 Mem_Free((msurface_t **)r_surfacelist);
12373 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12376 // if the model is static it doesn't matter what value we give for
12377 // wantnormals and wanttangents, so this logic uses only rules applicable
12378 // to a model, knowing that they are meaningless otherwise
12379 if (ent == r_refdef.scene.worldentity)
12380 RSurf_ActiveWorldEntity();
12381 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12382 RSurf_ActiveModelEntity(ent, false, false, false);
12384 RSurf_ActiveModelEntity(ent, true, true, true);
12385 else if (depthonly)
12387 switch (vid.renderpath)
12389 case RENDERPATH_GL20:
12390 case RENDERPATH_CGGL:
12391 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12393 case RENDERPATH_GL13:
12394 case RENDERPATH_GL11:
12395 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12401 switch (vid.renderpath)
12403 case RENDERPATH_GL20:
12404 case RENDERPATH_CGGL:
12405 RSurf_ActiveModelEntity(ent, true, true, false);
12407 case RENDERPATH_GL13:
12408 case RENDERPATH_GL11:
12409 RSurf_ActiveModelEntity(ent, true, false, false);
12414 surfaces = model->data_surfaces;
12415 update = model->brushq1.lightmapupdateflags;
12417 // update light styles
12418 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12420 model_brush_lightstyleinfo_t *style;
12421 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12423 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12425 int *list = style->surfacelist;
12426 style->value = r_refdef.scene.lightstylevalue[style->style];
12427 for (j = 0;j < style->numsurfaces;j++)
12428 update[list[j]] = true;
12433 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12437 R_DrawDebugModel();
12438 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12442 rsurface.uselightmaptexture = false;
12443 rsurface.texture = NULL;
12444 rsurface.rtlight = NULL;
12445 numsurfacelist = 0;
12446 // add visible surfaces to draw list
12447 for (i = 0;i < model->nummodelsurfaces;i++)
12448 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12449 // don't do anything if there were no surfaces
12450 if (!numsurfacelist)
12452 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12455 // update lightmaps if needed
12459 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12464 R_BuildLightMap(ent, surfaces + j);
12469 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12471 R_BuildLightMap(ent, surfaces + j);
12472 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12473 GL_AlphaTest(false);
12475 // add to stats if desired
12476 if (r_speeds.integer && !skysurfaces && !depthonly)
12478 r_refdef.stats.entities_surfaces += numsurfacelist;
12479 for (j = 0;j < numsurfacelist;j++)
12480 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12483 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12486 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12488 static texture_t texture;
12489 static msurface_t surface;
12490 const msurface_t *surfacelist = &surface;
12492 // fake enough texture and surface state to render this geometry
12494 texture.update_lastrenderframe = -1; // regenerate this texture
12495 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12496 texture.currentskinframe = skinframe;
12497 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12498 texture.specularscalemod = 1;
12499 texture.specularpowermod = 1;
12501 surface.texture = &texture;
12502 surface.num_triangles = numtriangles;
12503 surface.num_firsttriangle = firsttriangle;
12504 surface.num_vertices = numvertices;
12505 surface.num_firstvertex = firstvertex;
12508 rsurface.texture = R_GetCurrentTexture(surface.texture);
12509 rsurface.uselightmaptexture = false;
12510 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12513 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)
12515 static msurface_t surface;
12516 const msurface_t *surfacelist = &surface;
12518 // fake enough texture and surface state to render this geometry
12520 surface.texture = texture;
12521 surface.num_triangles = numtriangles;
12522 surface.num_firsttriangle = firsttriangle;
12523 surface.num_vertices = numvertices;
12524 surface.num_firstvertex = firstvertex;
12527 rsurface.texture = R_GetCurrentTexture(surface.texture);
12528 rsurface.uselightmaptexture = false;
12529 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);