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_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
96 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
97 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"};
98 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"};
99 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
100 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
101 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
102 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
103 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"};
105 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
106 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
107 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
108 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
109 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
110 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
111 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
112 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
114 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)"};
115 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"};
117 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
118 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
119 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
120 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
121 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
123 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
124 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
125 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
127 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)"};
128 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
129 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
130 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
131 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
132 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)"};
133 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)"};
134 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)"};
135 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)"};
137 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)"};
138 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
139 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"};
140 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
141 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
143 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
144 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
145 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
146 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
148 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
149 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
150 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
151 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
152 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
153 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
154 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
156 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
157 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
158 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
159 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)"};
161 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"};
163 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"};
165 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
167 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
168 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
169 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"};
170 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
171 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
172 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
173 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
174 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)"};
176 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
178 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)"};
180 extern cvar_t v_glslgamma;
182 extern qboolean v_flipped_state;
184 static struct r_bloomstate_s
189 int bloomwidth, bloomheight;
191 int screentexturewidth, screentextureheight;
192 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
194 int bloomtexturewidth, bloomtextureheight;
195 rtexture_t *texture_bloom;
197 // arrays for rendering the screen passes
198 float screentexcoord2f[8];
199 float bloomtexcoord2f[8];
200 float offsettexcoord2f[8];
202 r_viewport_t viewport;
206 r_waterstate_t r_waterstate;
208 /// shadow volume bsp struct with automatically growing nodes buffer
211 rtexture_t *r_texture_blanknormalmap;
212 rtexture_t *r_texture_white;
213 rtexture_t *r_texture_grey128;
214 rtexture_t *r_texture_black;
215 rtexture_t *r_texture_notexture;
216 rtexture_t *r_texture_whitecube;
217 rtexture_t *r_texture_normalizationcube;
218 rtexture_t *r_texture_fogattenuation;
219 rtexture_t *r_texture_gammaramps;
220 unsigned int r_texture_gammaramps_serial;
221 //rtexture_t *r_texture_fogintensity;
222 rtexture_t *r_texture_reflectcube;
224 // TODO: hash lookups?
225 typedef struct cubemapinfo_s
232 int r_texture_numcubemaps;
233 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
235 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
236 unsigned int r_numqueries;
237 unsigned int r_maxqueries;
239 typedef struct r_qwskincache_s
241 char name[MAX_QPATH];
242 skinframe_t *skinframe;
246 static r_qwskincache_t *r_qwskincache;
247 static int r_qwskincache_size;
249 /// vertex coordinates for a quad that covers the screen exactly
250 const float r_screenvertex3f[12] =
258 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
261 for (i = 0;i < verts;i++)
272 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
275 for (i = 0;i < verts;i++)
285 // FIXME: move this to client?
288 if (gamemode == GAME_NEHAHRA)
290 Cvar_Set("gl_fogenable", "0");
291 Cvar_Set("gl_fogdensity", "0.2");
292 Cvar_Set("gl_fogred", "0.3");
293 Cvar_Set("gl_foggreen", "0.3");
294 Cvar_Set("gl_fogblue", "0.3");
296 r_refdef.fog_density = 0;
297 r_refdef.fog_red = 0;
298 r_refdef.fog_green = 0;
299 r_refdef.fog_blue = 0;
300 r_refdef.fog_alpha = 1;
301 r_refdef.fog_start = 0;
302 r_refdef.fog_end = 16384;
303 r_refdef.fog_height = 1<<30;
304 r_refdef.fog_fadedepth = 128;
307 static void R_BuildBlankTextures(void)
309 unsigned char data[4];
310 data[2] = 128; // normal X
311 data[1] = 128; // normal Y
312 data[0] = 255; // normal Z
313 data[3] = 128; // height
314 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
319 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
324 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
329 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
332 static void R_BuildNoTexture(void)
335 unsigned char pix[16][16][4];
336 // this makes a light grey/dark grey checkerboard texture
337 for (y = 0;y < 16;y++)
339 for (x = 0;x < 16;x++)
341 if ((y < 8) ^ (x < 8))
357 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
360 static void R_BuildWhiteCube(void)
362 unsigned char data[6*1*1*4];
363 memset(data, 255, sizeof(data));
364 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
367 static void R_BuildNormalizationCube(void)
371 vec_t s, t, intensity;
374 data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
375 for (side = 0;side < 6;side++)
377 for (y = 0;y < NORMSIZE;y++)
379 for (x = 0;x < NORMSIZE;x++)
381 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
382 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
417 intensity = 127.0f / sqrt(DotProduct(v, v));
418 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
419 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
420 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
421 data[((side*64+y)*64+x)*4+3] = 255;
425 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
429 static void R_BuildFogTexture(void)
433 unsigned char data1[FOGWIDTH][4];
434 //unsigned char data2[FOGWIDTH][4];
437 r_refdef.fogmasktable_start = r_refdef.fog_start;
438 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
439 r_refdef.fogmasktable_range = r_refdef.fogrange;
440 r_refdef.fogmasktable_density = r_refdef.fog_density;
442 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
443 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
445 d = (x * r - r_refdef.fogmasktable_start);
446 if(developer_extra.integer)
447 Con_DPrintf("%f ", d);
449 if (r_fog_exp2.integer)
450 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
452 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
453 if(developer_extra.integer)
454 Con_DPrintf(" : %f ", alpha);
455 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
456 if(developer_extra.integer)
457 Con_DPrintf(" = %f\n", alpha);
458 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
461 for (x = 0;x < FOGWIDTH;x++)
463 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
468 //data2[x][0] = 255 - b;
469 //data2[x][1] = 255 - b;
470 //data2[x][2] = 255 - b;
473 if (r_texture_fogattenuation)
475 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
476 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
480 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
481 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
485 //=======================================================================================================================================================
487 static const char *builtinshaderstring =
488 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
489 "// written by Forest 'LordHavoc' Hale\n"
490 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
492 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
495 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
496 "#define USELIGHTMAP\n"
498 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
499 "#define USEEYEVECTOR\n"
502 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
503 "# extension GL_ARB_texture_rectangle : enable\n"
506 "#ifdef USESHADOWMAP2D\n"
507 "# ifdef GL_EXT_gpu_shader4\n"
508 "# extension GL_EXT_gpu_shader4 : enable\n"
510 "# ifdef GL_ARB_texture_gather\n"
511 "# extension GL_ARB_texture_gather : enable\n"
513 "# ifdef GL_AMD_texture_texture4\n"
514 "# extension GL_AMD_texture_texture4 : enable\n"
519 "#ifdef USESHADOWMAPCUBE\n"
520 "# extension GL_EXT_gpu_shader4 : enable\n"
523 "//#ifdef USESHADOWSAMPLER\n"
524 "//# extension GL_ARB_shadow : enable\n"
527 "//#ifdef __GLSL_CG_DATA_TYPES\n"
528 "//# define myhalf half\n"
529 "//# define myhalf2 half2\n"
530 "//# define myhalf3 half3\n"
531 "//# define myhalf4 half4\n"
533 "# define myhalf float\n"
534 "# define myhalf2 vec2\n"
535 "# define myhalf3 vec3\n"
536 "# define myhalf4 vec4\n"
539 "#ifdef VERTEX_SHADER\n"
540 "uniform mat4 ModelViewProjectionMatrix;\n"
543 "#ifdef MODE_DEPTH_OR_SHADOW\n"
544 "#ifdef VERTEX_SHADER\n"
547 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
550 "#else // !MODE_DEPTH_ORSHADOW\n"
555 "#ifdef MODE_SHOWDEPTH\n"
556 "#ifdef VERTEX_SHADER\n"
559 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
560 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
564 "#ifdef FRAGMENT_SHADER\n"
567 " gl_FragColor = gl_Color;\n"
570 "#else // !MODE_SHOWDEPTH\n"
575 "#ifdef MODE_POSTPROCESS\n"
576 "varying vec2 TexCoord1;\n"
577 "varying vec2 TexCoord2;\n"
579 "#ifdef VERTEX_SHADER\n"
582 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
583 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
585 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
590 "#ifdef FRAGMENT_SHADER\n"
591 "uniform sampler2D Texture_First;\n"
593 "uniform sampler2D Texture_Second;\n"
595 "#ifdef USEGAMMARAMPS\n"
596 "uniform sampler2D Texture_GammaRamps;\n"
598 "#ifdef USESATURATION\n"
599 "uniform float Saturation;\n"
601 "#ifdef USEVIEWTINT\n"
602 "uniform vec4 ViewTintColor;\n"
604 "//uncomment these if you want to use them:\n"
605 "uniform vec4 UserVec1;\n"
606 "uniform vec4 UserVec2;\n"
607 "// uniform vec4 UserVec3;\n"
608 "// uniform vec4 UserVec4;\n"
609 "// uniform float ClientTime;\n"
610 "uniform vec2 PixelSize;\n"
613 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
615 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
617 "#ifdef USEVIEWTINT\n"
618 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
621 "#ifdef USEPOSTPROCESSING\n"
622 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
623 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
624 " float sobel = 1.0;\n"
625 " // vec2 ts = textureSize(Texture_First, 0);\n"
626 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
627 " vec2 px = PixelSize;\n"
628 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
629 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
630 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
631 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
632 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
633 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
634 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
635 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
636 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
637 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
638 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
639 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
640 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
641 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
642 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
643 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
644 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
645 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
646 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
647 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
648 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
649 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
650 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
651 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
652 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
653 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
654 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
655 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
656 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
657 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
658 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
659 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
662 "#ifdef USESATURATION\n"
663 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
664 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
665 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
666 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
669 "#ifdef USEGAMMARAMPS\n"
670 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
671 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
672 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
676 "#else // !MODE_POSTPROCESS\n"
681 "#ifdef MODE_GENERIC\n"
682 "#ifdef USEDIFFUSE\n"
683 "varying vec2 TexCoord1;\n"
685 "#ifdef USESPECULAR\n"
686 "varying vec2 TexCoord2;\n"
688 "#ifdef VERTEX_SHADER\n"
691 " gl_FrontColor = gl_Color;\n"
692 "#ifdef USEDIFFUSE\n"
693 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
695 "#ifdef USESPECULAR\n"
696 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
698 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
702 "#ifdef FRAGMENT_SHADER\n"
703 "#ifdef USEDIFFUSE\n"
704 "uniform sampler2D Texture_First;\n"
706 "#ifdef USESPECULAR\n"
707 "uniform sampler2D Texture_Second;\n"
712 " gl_FragColor = gl_Color;\n"
713 "#ifdef USEDIFFUSE\n"
714 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
717 "#ifdef USESPECULAR\n"
718 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
719 "# ifdef USECOLORMAPPING\n"
720 " gl_FragColor *= tex2;\n"
723 " gl_FragColor += tex2;\n"
725 "# ifdef USEVERTEXTEXTUREBLEND\n"
726 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
731 "#else // !MODE_GENERIC\n"
736 "#ifdef MODE_BLOOMBLUR\n"
737 "varying TexCoord;\n"
738 "#ifdef VERTEX_SHADER\n"
741 " gl_FrontColor = gl_Color;\n"
742 " TexCoord = gl_MultiTexCoord0.xy;\n"
743 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
747 "#ifdef FRAGMENT_SHADER\n"
748 "uniform sampler2D Texture_First;\n"
749 "uniform vec4 BloomBlur_Parameters;\n"
754 " vec2 tc = TexCoord;\n"
755 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
756 " tc += BloomBlur_Parameters.xy;\n"
757 " for (i = 1;i < SAMPLES;i++)\n"
759 " color += texture2D(Texture_First, tc).rgb;\n"
760 " tc += BloomBlur_Parameters.xy;\n"
762 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
765 "#else // !MODE_BLOOMBLUR\n"
766 "#ifdef MODE_REFRACTION\n"
767 "varying vec2 TexCoord;\n"
768 "varying vec4 ModelViewProjectionPosition;\n"
769 "uniform mat4 TexMatrix;\n"
770 "#ifdef VERTEX_SHADER\n"
774 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
775 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
776 " ModelViewProjectionPosition = gl_Position;\n"
780 "#ifdef FRAGMENT_SHADER\n"
781 "uniform sampler2D Texture_Normal;\n"
782 "uniform sampler2D Texture_Refraction;\n"
783 "uniform sampler2D Texture_Reflection;\n"
785 "uniform vec4 DistortScaleRefractReflect;\n"
786 "uniform vec4 ScreenScaleRefractReflect;\n"
787 "uniform vec4 ScreenCenterRefractReflect;\n"
788 "uniform vec4 RefractColor;\n"
789 "uniform vec4 ReflectColor;\n"
790 "uniform float ReflectFactor;\n"
791 "uniform float ReflectOffset;\n"
795 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
796 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
797 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
798 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
799 " // FIXME temporary hack to detect the case that the reflection\n"
800 " // gets blackened at edges due to leaving the area that contains actual\n"
802 " // Remove this 'ack once we have a better way to stop this thing from\n"
804 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
805 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
806 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
807 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
808 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
809 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
812 "#else // !MODE_REFRACTION\n"
817 "#ifdef MODE_WATER\n"
818 "varying vec2 TexCoord;\n"
819 "varying vec3 EyeVector;\n"
820 "varying vec4 ModelViewProjectionPosition;\n"
821 "#ifdef VERTEX_SHADER\n"
822 "uniform vec3 EyePosition;\n"
823 "uniform mat4 TexMatrix;\n"
827 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
828 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
829 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
830 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
831 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
832 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
833 " ModelViewProjectionPosition = gl_Position;\n"
837 "#ifdef FRAGMENT_SHADER\n"
838 "uniform sampler2D Texture_Normal;\n"
839 "uniform sampler2D Texture_Refraction;\n"
840 "uniform sampler2D Texture_Reflection;\n"
842 "uniform vec4 DistortScaleRefractReflect;\n"
843 "uniform vec4 ScreenScaleRefractReflect;\n"
844 "uniform vec4 ScreenCenterRefractReflect;\n"
845 "uniform vec4 RefractColor;\n"
846 "uniform vec4 ReflectColor;\n"
847 "uniform float ReflectFactor;\n"
848 "uniform float ReflectOffset;\n"
852 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
853 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
854 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
855 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
856 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
857 " // FIXME temporary hack to detect the case that the reflection\n"
858 " // gets blackened at edges due to leaving the area that contains actual\n"
860 " // Remove this 'ack once we have a better way to stop this thing from\n"
862 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
863 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
864 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
865 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
866 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
867 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
868 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
869 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
870 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
871 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
872 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
873 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
876 "#else // !MODE_WATER\n"
881 "// common definitions between vertex shader and fragment shader:\n"
883 "varying vec2 TexCoord;\n"
884 "#ifdef USEVERTEXTEXTUREBLEND\n"
885 "varying vec2 TexCoord2;\n"
887 "#ifdef USELIGHTMAP\n"
888 "varying vec2 TexCoordLightmap;\n"
891 "#ifdef MODE_LIGHTSOURCE\n"
892 "varying vec3 CubeVector;\n"
895 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
896 "varying vec3 LightVector;\n"
899 "#ifdef USEEYEVECTOR\n"
900 "varying vec3 EyeVector;\n"
903 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
906 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
907 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
908 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
909 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
912 "#ifdef USEREFLECTION\n"
913 "varying vec4 ModelViewProjectionPosition;\n"
915 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
916 "uniform vec3 LightPosition;\n"
917 "varying vec4 ModelViewPosition;\n"
920 "#ifdef MODE_LIGHTSOURCE\n"
921 "uniform vec3 LightPosition;\n"
923 "uniform vec3 EyePosition;\n"
924 "#ifdef MODE_LIGHTDIRECTION\n"
925 "uniform vec3 LightDir;\n"
927 "uniform vec4 FogPlane;\n"
929 "#ifdef USESHADOWMAPORTHO\n"
930 "varying vec3 ShadowMapTC;\n"
937 "// 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"
939 "// fragment shader specific:\n"
940 "#ifdef FRAGMENT_SHADER\n"
942 "uniform sampler2D Texture_Normal;\n"
943 "uniform sampler2D Texture_Color;\n"
944 "uniform sampler2D Texture_Gloss;\n"
946 "uniform sampler2D Texture_Glow;\n"
948 "#ifdef USEVERTEXTEXTUREBLEND\n"
949 "uniform sampler2D Texture_SecondaryNormal;\n"
950 "uniform sampler2D Texture_SecondaryColor;\n"
951 "uniform sampler2D Texture_SecondaryGloss;\n"
953 "uniform sampler2D Texture_SecondaryGlow;\n"
956 "#ifdef USECOLORMAPPING\n"
957 "uniform sampler2D Texture_Pants;\n"
958 "uniform sampler2D Texture_Shirt;\n"
961 "uniform sampler2D Texture_FogMask;\n"
963 "#ifdef USELIGHTMAP\n"
964 "uniform sampler2D Texture_Lightmap;\n"
966 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
967 "uniform sampler2D Texture_Deluxemap;\n"
969 "#ifdef USEREFLECTION\n"
970 "uniform sampler2D Texture_Reflection;\n"
973 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
974 "uniform sampler2D Texture_ScreenDepth;\n"
975 "uniform sampler2D Texture_ScreenNormalMap;\n"
977 "#ifdef USEDEFERREDLIGHTMAP\n"
978 "uniform sampler2D Texture_ScreenDiffuse;\n"
979 "uniform sampler2D Texture_ScreenSpecular;\n"
982 "uniform myhalf3 Color_Pants;\n"
983 "uniform myhalf3 Color_Shirt;\n"
984 "uniform myhalf3 FogColor;\n"
987 "uniform float FogRangeRecip;\n"
988 "uniform float FogPlaneViewDist;\n"
989 "uniform float FogHeightFade;\n"
990 "float FogVertex(void)\n"
992 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
993 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
995 "#ifdef USEFOGOUTSIDE\n"
996 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
998 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1000 " return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1004 "#ifdef USEOFFSETMAPPING\n"
1005 "uniform float OffsetMapping_Scale;\n"
1006 "vec2 OffsetMapping(vec2 TexCoord)\n"
1008 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1009 " // 14 sample relief mapping: linear search and then binary search\n"
1010 " // this basically steps forward a small amount repeatedly until it finds\n"
1011 " // itself inside solid, then jitters forward and back using decreasing\n"
1012 " // amounts to find the impact\n"
1013 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1014 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1015 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1016 " vec3 RT = vec3(TexCoord, 1);\n"
1017 " OffsetVector *= 0.1;\n"
1018 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1019 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1020 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1021 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1022 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1023 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1024 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1025 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1026 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1027 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1028 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1029 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1030 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1031 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1034 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1035 " // this basically moves forward the full distance, and then backs up based\n"
1036 " // on height of samples\n"
1037 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1038 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1039 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1040 " TexCoord += OffsetVector;\n"
1041 " OffsetVector *= 0.333;\n"
1042 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1043 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1044 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1045 " return TexCoord;\n"
1048 "#endif // USEOFFSETMAPPING\n"
1050 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1051 "uniform sampler2D Texture_Attenuation;\n"
1052 "uniform samplerCube Texture_Cube;\n"
1055 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1057 "#ifdef USESHADOWMAPRECT\n"
1058 "# ifdef USESHADOWSAMPLER\n"
1059 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1061 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1065 "#ifdef USESHADOWMAP2D\n"
1066 "# ifdef USESHADOWSAMPLER\n"
1067 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1069 "uniform sampler2D Texture_ShadowMap2D;\n"
1073 "#ifdef USESHADOWMAPVSDCT\n"
1074 "uniform samplerCube Texture_CubeProjection;\n"
1077 "#ifdef USESHADOWMAPCUBE\n"
1078 "# ifdef USESHADOWSAMPLER\n"
1079 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1081 "uniform samplerCube Texture_ShadowMapCube;\n"
1085 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1086 "uniform vec2 ShadowMap_TextureScale;\n"
1087 "uniform vec4 ShadowMap_Parameters;\n"
1090 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1091 "# ifdef USESHADOWMAPORTHO\n"
1092 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1094 "# ifdef USESHADOWMAPVSDCT\n"
1095 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1097 " vec3 adir = abs(dir);\n"
1098 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1099 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1100 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1103 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1105 " vec3 adir = abs(dir);\n"
1106 " float ma = adir.z;\n"
1107 " vec4 proj = vec4(dir, 2.5);\n"
1108 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1109 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1110 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1111 " return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1115 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1117 "#ifdef USESHADOWMAPCUBE\n"
1118 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1120 " vec3 adir = abs(dir);\n"
1121 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1125 "# ifdef USESHADOWMAPRECT\n"
1126 "float ShadowMapCompare(vec3 dir)\n"
1128 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1130 "# ifdef USESHADOWSAMPLER\n"
1132 "# ifdef USESHADOWMAPPCF\n"
1133 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1134 " 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"
1136 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1141 "# ifdef USESHADOWMAPPCF\n"
1142 "# if USESHADOWMAPPCF > 1\n"
1143 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1144 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1145 " 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"
1146 " 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"
1147 " 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"
1148 " 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"
1149 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1150 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1152 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1153 " vec2 offset = fract(shadowmaptc.xy);\n"
1154 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1155 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1156 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1157 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1158 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1161 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1165 "# ifdef USESHADOWMAPORTHO\n"
1166 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1173 "# ifdef USESHADOWMAP2D\n"
1174 "float ShadowMapCompare(vec3 dir)\n"
1176 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1179 "# ifdef USESHADOWSAMPLER\n"
1180 "# ifdef USESHADOWMAPPCF\n"
1181 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1182 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1183 " 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"
1185 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1188 "# ifdef USESHADOWMAPPCF\n"
1189 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1190 "# ifdef GL_ARB_texture_gather\n"
1191 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1193 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1195 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1196 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1197 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1198 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1199 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1200 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1201 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1202 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1204 "# ifdef GL_EXT_gpu_shader4\n"
1205 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1207 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1209 "# if USESHADOWMAPPCF > 1\n"
1210 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1211 " center *= ShadowMap_TextureScale;\n"
1212 " 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"
1213 " 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"
1214 " 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"
1215 " 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"
1216 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1217 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1219 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1220 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1221 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1222 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1223 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1224 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1228 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1231 "# ifdef USESHADOWMAPORTHO\n"
1232 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1239 "# ifdef USESHADOWMAPCUBE\n"
1240 "float ShadowMapCompare(vec3 dir)\n"
1242 " // apply depth texture cubemap as light filter\n"
1243 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1245 "# ifdef USESHADOWSAMPLER\n"
1246 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1248 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1253 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1254 "#endif // FRAGMENT_SHADER\n"
1259 "#ifdef MODE_DEFERREDGEOMETRY\n"
1260 "#ifdef VERTEX_SHADER\n"
1261 "uniform mat4 TexMatrix;\n"
1262 "#ifdef USEVERTEXTEXTUREBLEND\n"
1263 "uniform mat4 BackgroundTexMatrix;\n"
1265 "uniform mat4 ModelViewMatrix;\n"
1268 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1269 "#ifdef USEVERTEXTEXTUREBLEND\n"
1270 " gl_FrontColor = gl_Color;\n"
1271 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1274 " // transform unnormalized eye direction into tangent space\n"
1275 "#ifdef USEOFFSETMAPPING\n"
1276 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1277 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1278 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1279 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1282 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1283 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1284 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1285 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1287 "#endif // VERTEX_SHADER\n"
1289 "#ifdef FRAGMENT_SHADER\n"
1292 "#ifdef USEOFFSETMAPPING\n"
1293 " // apply offsetmapping\n"
1294 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1295 "#define TexCoord TexCoordOffset\n"
1298 "#ifdef USEALPHAKILL\n"
1299 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1303 "#ifdef USEVERTEXTEXTUREBLEND\n"
1304 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1305 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1306 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1307 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1310 "#ifdef USEVERTEXTEXTUREBLEND\n"
1311 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1312 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1314 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1315 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1318 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1320 "#endif // FRAGMENT_SHADER\n"
1321 "#else // !MODE_DEFERREDGEOMETRY\n"
1326 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1327 "#ifdef VERTEX_SHADER\n"
1328 "uniform mat4 ModelViewMatrix;\n"
1331 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1332 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1334 "#endif // VERTEX_SHADER\n"
1336 "#ifdef FRAGMENT_SHADER\n"
1337 "uniform mat4 ViewToLight;\n"
1338 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1339 "uniform vec2 ScreenToDepth;\n"
1340 "uniform myhalf3 DeferredColor_Ambient;\n"
1341 "uniform myhalf3 DeferredColor_Diffuse;\n"
1342 "#ifdef USESPECULAR\n"
1343 "uniform myhalf3 DeferredColor_Specular;\n"
1344 "uniform myhalf SpecularPower;\n"
1346 "uniform myhalf2 PixelToScreenTexCoord;\n"
1349 " // calculate viewspace pixel position\n"
1350 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1352 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1353 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1354 " // decode viewspace pixel normal\n"
1355 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1356 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1357 " // surfacenormal = pixel normal in viewspace\n"
1358 " // LightVector = pixel to light in viewspace\n"
1359 " // CubeVector = position in lightspace\n"
1360 " // eyevector = pixel to view in viewspace\n"
1361 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1362 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1363 "#ifdef USEDIFFUSE\n"
1364 " // calculate diffuse shading\n"
1365 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1366 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1368 "#ifdef USESPECULAR\n"
1369 " // calculate directional shading\n"
1370 " vec3 eyevector = position * -1.0;\n"
1371 "# ifdef USEEXACTSPECULARMATH\n"
1372 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1374 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1375 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1379 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1380 " fade *= ShadowMapCompare(CubeVector);\n"
1383 "#ifdef USEDIFFUSE\n"
1384 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1386 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1388 "#ifdef USESPECULAR\n"
1389 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1391 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1394 "# ifdef USECUBEFILTER\n"
1395 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1396 " gl_FragData[0].rgb *= cubecolor;\n"
1397 " gl_FragData[1].rgb *= cubecolor;\n"
1400 "#endif // FRAGMENT_SHADER\n"
1401 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1406 "#ifdef VERTEX_SHADER\n"
1407 "uniform mat4 TexMatrix;\n"
1408 "#ifdef USEVERTEXTEXTUREBLEND\n"
1409 "uniform mat4 BackgroundTexMatrix;\n"
1411 "#ifdef MODE_LIGHTSOURCE\n"
1412 "uniform mat4 ModelToLight;\n"
1414 "#ifdef USESHADOWMAPORTHO\n"
1415 "uniform mat4 ShadowMapMatrix;\n"
1419 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1420 " gl_FrontColor = gl_Color;\n"
1422 " // copy the surface texcoord\n"
1423 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1424 "#ifdef USEVERTEXTEXTUREBLEND\n"
1425 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1427 "#ifdef USELIGHTMAP\n"
1428 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1431 "#ifdef MODE_LIGHTSOURCE\n"
1432 " // transform vertex position into light attenuation/cubemap space\n"
1433 " // (-1 to +1 across the light box)\n"
1434 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1436 "# ifdef USEDIFFUSE\n"
1437 " // transform unnormalized light direction into tangent space\n"
1438 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1439 " // normalize it per pixel)\n"
1440 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1441 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1442 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1443 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1447 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1448 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1449 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1450 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1453 " // transform unnormalized eye direction into tangent space\n"
1454 "#ifdef USEEYEVECTOR\n"
1455 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1456 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1457 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1458 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1462 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1463 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1466 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1467 " VectorS = gl_MultiTexCoord1.xyz;\n"
1468 " VectorT = gl_MultiTexCoord2.xyz;\n"
1469 " VectorR = gl_MultiTexCoord3.xyz;\n"
1472 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1473 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1475 "#ifdef USESHADOWMAPORTHO\n"
1476 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1479 "#ifdef USEREFLECTION\n"
1480 " ModelViewProjectionPosition = gl_Position;\n"
1483 "#endif // VERTEX_SHADER\n"
1488 "#ifdef FRAGMENT_SHADER\n"
1489 "#ifdef USEDEFERREDLIGHTMAP\n"
1490 "uniform myhalf2 PixelToScreenTexCoord;\n"
1491 "uniform myhalf3 DeferredMod_Diffuse;\n"
1492 "uniform myhalf3 DeferredMod_Specular;\n"
1494 "uniform myhalf3 Color_Ambient;\n"
1495 "uniform myhalf3 Color_Diffuse;\n"
1496 "uniform myhalf3 Color_Specular;\n"
1497 "uniform myhalf SpecularPower;\n"
1499 "uniform myhalf3 Color_Glow;\n"
1501 "uniform myhalf Alpha;\n"
1502 "#ifdef USEREFLECTION\n"
1503 "uniform vec4 DistortScaleRefractReflect;\n"
1504 "uniform vec4 ScreenScaleRefractReflect;\n"
1505 "uniform vec4 ScreenCenterRefractReflect;\n"
1506 "uniform myhalf4 ReflectColor;\n"
1508 "#ifdef USEREFLECTCUBE\n"
1509 "uniform mat4 ModelToReflectCube;\n"
1510 "uniform sampler2D Texture_ReflectMask;\n"
1511 "uniform samplerCube Texture_ReflectCube;\n"
1513 "#ifdef MODE_LIGHTDIRECTION\n"
1514 "uniform myhalf3 LightColor;\n"
1516 "#ifdef MODE_LIGHTSOURCE\n"
1517 "uniform myhalf3 LightColor;\n"
1521 "#ifdef USEOFFSETMAPPING\n"
1522 " // apply offsetmapping\n"
1523 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1524 "#define TexCoord TexCoordOffset\n"
1527 " // combine the diffuse textures (base, pants, shirt)\n"
1528 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1529 "#ifdef USEALPHAKILL\n"
1530 " if (color.a < 0.5)\n"
1533 " color.a *= Alpha;\n"
1534 "#ifdef USECOLORMAPPING\n"
1535 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1537 "#ifdef USEVERTEXTEXTUREBLEND\n"
1538 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1539 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1540 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1541 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1543 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1546 " // get the surface normal\n"
1547 "#ifdef USEVERTEXTEXTUREBLEND\n"
1548 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1550 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1553 " // get the material colors\n"
1554 " myhalf3 diffusetex = color.rgb;\n"
1555 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1556 "# ifdef USEVERTEXTEXTUREBLEND\n"
1557 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1559 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1563 "#ifdef USEREFLECTCUBE\n"
1564 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1565 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1566 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1567 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1573 "#ifdef MODE_LIGHTSOURCE\n"
1574 " // light source\n"
1575 "#ifdef USEDIFFUSE\n"
1576 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1577 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1578 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1579 "#ifdef USESPECULAR\n"
1580 "#ifdef USEEXACTSPECULARMATH\n"
1581 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1583 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1584 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1586 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1589 " color.rgb = diffusetex * Color_Ambient;\n"
1591 " color.rgb *= LightColor;\n"
1592 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1593 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1594 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1596 "# ifdef USECUBEFILTER\n"
1597 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1599 "#endif // MODE_LIGHTSOURCE\n"
1604 "#ifdef MODE_LIGHTDIRECTION\n"
1606 "#ifdef USEDIFFUSE\n"
1607 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1609 "#define lightcolor LightColor\n"
1610 "#endif // MODE_LIGHTDIRECTION\n"
1611 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1613 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1614 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1615 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1616 " // convert modelspace light vector to tangentspace\n"
1617 " myhalf3 lightnormal;\n"
1618 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1619 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1620 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1621 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1622 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1623 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1624 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1625 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1626 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1627 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1628 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1629 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1630 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1631 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1632 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1634 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1635 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1636 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1642 "#ifdef MODE_LIGHTMAP\n"
1643 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1644 "#endif // MODE_LIGHTMAP\n"
1645 "#ifdef MODE_VERTEXCOLOR\n"
1646 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1647 "#endif // MODE_VERTEXCOLOR\n"
1648 "#ifdef MODE_FLATCOLOR\n"
1649 " color.rgb = diffusetex * Color_Ambient;\n"
1650 "#endif // MODE_FLATCOLOR\n"
1656 "# ifdef USEDIFFUSE\n"
1657 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1658 "# ifdef USESPECULAR\n"
1659 "# ifdef USEEXACTSPECULARMATH\n"
1660 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1662 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1663 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1665 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1667 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1670 " color.rgb = diffusetex * Color_Ambient;\n"
1674 "#ifdef USESHADOWMAPORTHO\n"
1675 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1678 "#ifdef USEDEFERREDLIGHTMAP\n"
1679 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1680 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1681 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1685 "#ifdef USEVERTEXTEXTUREBLEND\n"
1686 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1688 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1693 "#ifdef MODE_LIGHTSOURCE\n"
1694 " color.rgb *= myhalf(FogVertex());\n"
1696 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1700 " // 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"
1701 "#ifdef USEREFLECTION\n"
1702 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1703 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1704 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1705 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1706 " // FIXME temporary hack to detect the case that the reflection\n"
1707 " // gets blackened at edges due to leaving the area that contains actual\n"
1709 " // Remove this 'ack once we have a better way to stop this thing from\n"
1711 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1712 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1713 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1714 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1715 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1716 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1719 " gl_FragColor = vec4(color);\n"
1721 "#endif // FRAGMENT_SHADER\n"
1723 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1724 "#endif // !MODE_DEFERREDGEOMETRY\n"
1725 "#endif // !MODE_WATER\n"
1726 "#endif // !MODE_REFRACTION\n"
1727 "#endif // !MODE_BLOOMBLUR\n"
1728 "#endif // !MODE_GENERIC\n"
1729 "#endif // !MODE_POSTPROCESS\n"
1730 "#endif // !MODE_SHOWDEPTH\n"
1731 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1735 =========================================================================================================================================================
1739 =========================================================================================================================================================
1743 =========================================================================================================================================================
1747 =========================================================================================================================================================
1751 =========================================================================================================================================================
1755 =========================================================================================================================================================
1759 =========================================================================================================================================================
1762 const char *builtincgshaderstring =
1763 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1764 "// written by Forest 'LordHavoc' Hale\n"
1765 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1767 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1770 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1771 "#define USELIGHTMAP\n"
1773 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1774 "#define USEEYEVECTOR\n"
1777 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1778 "#ifdef VERTEX_SHADER\n"
1781 "float4 gl_Vertex : POSITION,\n"
1782 "uniform float4x4 ModelViewProjectionMatrix,\n"
1783 "out float4 gl_Position : POSITION\n"
1786 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1789 "#else // !MODE_DEPTH_ORSHADOW\n"
1794 "#ifdef MODE_SHOWDEPTH\n"
1795 "#ifdef VERTEX_SHADER\n"
1798 "float4 gl_Vertex : POSITION,\n"
1799 "uniform float4x4 ModelViewProjectionMatrix,\n"
1800 "out float4 gl_Position : POSITION,\n"
1801 "out float4 gl_FrontColor : COLOR0\n"
1804 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1805 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1809 "#ifdef FRAGMENT_SHADER\n"
1812 "float4 gl_FrontColor : COLOR0,\n"
1813 "out float4 gl_FragColor : COLOR\n"
1816 " gl_FragColor = gl_FrontColor;\n"
1819 "#else // !MODE_SHOWDEPTH\n"
1824 "#ifdef MODE_POSTPROCESS\n"
1826 "#ifdef VERTEX_SHADER\n"
1829 "float4 gl_Vertex : POSITION,\n"
1830 "uniform float4x4 ModelViewProjectionMatrix,\n"
1831 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1832 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1833 "out float4 gl_Position : POSITION,\n"
1834 "out float2 TexCoord1 : TEXCOORD0,\n"
1835 "out float2 TexCoord2 : TEXCOORD1\n"
1838 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1839 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1841 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1846 "#ifdef FRAGMENT_SHADER\n"
1849 "float2 TexCoord1 : TEXCOORD0,\n"
1850 "float2 TexCoord2 : TEXCOORD1,\n"
1851 "uniform sampler2D Texture_First,\n"
1853 "uniform sampler2D Texture_Second,\n"
1855 "#ifdef USEGAMMARAMPS\n"
1856 "uniform sampler2D Texture_GammaRamps,\n"
1858 "#ifdef USESATURATION\n"
1859 "uniform float Saturation,\n"
1861 "#ifdef USEVIEWTINT\n"
1862 "uniform float4 ViewTintColor,\n"
1864 "uniform float4 UserVec1,\n"
1865 "uniform float4 UserVec2,\n"
1866 "uniform float4 UserVec3,\n"
1867 "uniform float4 UserVec4,\n"
1868 "uniform float ClientTime,\n"
1869 "uniform float2 PixelSize,\n"
1870 "out float4 gl_FragColor : COLOR\n"
1873 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1875 " gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1877 "#ifdef USEVIEWTINT\n"
1878 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1881 "#ifdef USEPOSTPROCESSING\n"
1882 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1883 "// 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"
1884 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1885 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1886 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1887 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1888 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1889 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1892 "#ifdef USESATURATION\n"
1893 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1894 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1895 " //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1896 " gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1899 "#ifdef USEGAMMARAMPS\n"
1900 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1901 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1902 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1906 "#else // !MODE_POSTPROCESS\n"
1911 "#ifdef MODE_GENERIC\n"
1912 "#ifdef VERTEX_SHADER\n"
1915 "float4 gl_Vertex : POSITION,\n"
1916 "uniform float4x4 ModelViewProjectionMatrix,\n"
1917 "float4 gl_Color : COLOR0,\n"
1918 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1919 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1920 "out float4 gl_Position : POSITION,\n"
1921 "out float4 gl_FrontColor : COLOR,\n"
1922 "out float2 TexCoord1 : TEXCOORD0,\n"
1923 "out float2 TexCoord2 : TEXCOORD1\n"
1926 " gl_FrontColor = gl_Color;\n"
1927 "#ifdef USEDIFFUSE\n"
1928 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1930 "#ifdef USESPECULAR\n"
1931 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1933 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1937 "#ifdef FRAGMENT_SHADER\n"
1941 "float4 gl_FrontColor : COLOR,\n"
1942 "float2 TexCoord1 : TEXCOORD0,\n"
1943 "float2 TexCoord2 : TEXCOORD1,\n"
1944 "#ifdef USEDIFFUSE\n"
1945 "uniform sampler2D Texture_First,\n"
1947 "#ifdef USESPECULAR\n"
1948 "uniform sampler2D Texture_Second,\n"
1950 "out float4 gl_FragColor : COLOR\n"
1953 " gl_FragColor = gl_FrontColor;\n"
1954 "#ifdef USEDIFFUSE\n"
1955 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1958 "#ifdef USESPECULAR\n"
1959 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1960 "# ifdef USECOLORMAPPING\n"
1961 " gl_FragColor *= tex2;\n"
1964 " gl_FragColor += tex2;\n"
1966 "# ifdef USEVERTEXTEXTUREBLEND\n"
1967 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1972 "#else // !MODE_GENERIC\n"
1977 "#ifdef MODE_BLOOMBLUR\n"
1978 "#ifdef VERTEX_SHADER\n"
1981 "float4 gl_Vertex : POSITION,\n"
1982 "uniform float4x4 ModelViewProjectionMatrix,\n"
1983 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1984 "out float4 gl_Position : POSITION,\n"
1985 "out float2 TexCoord : TEXCOORD0\n"
1988 " TexCoord = gl_MultiTexCoord0.xy;\n"
1989 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1993 "#ifdef FRAGMENT_SHADER\n"
1997 "float2 TexCoord : TEXCOORD0,\n"
1998 "uniform sampler2D Texture_First,\n"
1999 "uniform float4 BloomBlur_Parameters,\n"
2000 "out float4 gl_FragColor : COLOR\n"
2004 " float2 tc = TexCoord;\n"
2005 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2006 " tc += BloomBlur_Parameters.xy;\n"
2007 " for (i = 1;i < SAMPLES;i++)\n"
2009 " color += tex2D(Texture_First, tc).rgb;\n"
2010 " tc += BloomBlur_Parameters.xy;\n"
2012 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2015 "#else // !MODE_BLOOMBLUR\n"
2016 "#ifdef MODE_REFRACTION\n"
2017 "#ifdef VERTEX_SHADER\n"
2020 "float4 gl_Vertex : POSITION,\n"
2021 "uniform float4x4 ModelViewProjectionMatrix,\n"
2022 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2023 "uniform float4x4 TexMatrix,\n"
2024 "uniform float3 EyePosition,\n"
2025 "out float4 gl_Position : POSITION,\n"
2026 "out float2 TexCoord : TEXCOORD0,\n"
2027 "out float3 EyeVector : TEXCOORD1,\n"
2028 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2031 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2032 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2033 " ModelViewProjectionPosition = gl_Position;\n"
2037 "#ifdef FRAGMENT_SHADER\n"
2040 "float2 TexCoord : TEXCOORD0,\n"
2041 "float3 EyeVector : TEXCOORD1,\n"
2042 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2043 "uniform sampler2D Texture_Normal,\n"
2044 "uniform sampler2D Texture_Refraction,\n"
2045 "uniform sampler2D Texture_Reflection,\n"
2046 "uniform float4 DistortScaleRefractReflect,\n"
2047 "uniform float4 ScreenScaleRefractReflect,\n"
2048 "uniform float4 ScreenCenterRefractReflect,\n"
2049 "uniform float4 RefractColor,\n"
2050 "out float4 gl_FragColor : COLOR\n"
2053 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2054 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2055 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2056 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2057 " // FIXME temporary hack to detect the case that the reflection\n"
2058 " // gets blackened at edges due to leaving the area that contains actual\n"
2060 " // Remove this 'ack once we have a better way to stop this thing from\n"
2062 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2063 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2064 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2065 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2066 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2067 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2070 "#else // !MODE_REFRACTION\n"
2075 "#ifdef MODE_WATER\n"
2076 "#ifdef VERTEX_SHADER\n"
2080 "float4 gl_Vertex : POSITION,\n"
2081 "uniform float4x4 ModelViewProjectionMatrix,\n"
2082 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2083 "uniform float4x4 TexMatrix,\n"
2084 "uniform float3 EyePosition,\n"
2085 "out float4 gl_Position : POSITION,\n"
2086 "out float2 TexCoord : TEXCOORD0,\n"
2087 "out float3 EyeVector : TEXCOORD1,\n"
2088 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2091 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2092 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2093 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2094 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2095 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2096 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2097 " ModelViewProjectionPosition = gl_Position;\n"
2101 "#ifdef FRAGMENT_SHADER\n"
2104 "float2 TexCoord : TEXCOORD0,\n"
2105 "float3 EyeVector : TEXCOORD1,\n"
2106 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2107 "uniform sampler2D Texture_Normal,\n"
2108 "uniform sampler2D Texture_Refraction,\n"
2109 "uniform sampler2D Texture_Reflection,\n"
2110 "uniform float4 DistortScaleRefractReflect,\n"
2111 "uniform float4 ScreenScaleRefractReflect,\n"
2112 "uniform float4 ScreenCenterRefractReflect,\n"
2113 "uniform float4 RefractColor,\n"
2114 "uniform float4 ReflectColor,\n"
2115 "uniform float ReflectFactor,\n"
2116 "uniform float ReflectOffset,\n"
2117 "out float4 gl_FragColor : COLOR\n"
2120 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2121 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2122 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2123 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2124 " // FIXME temporary hack to detect the case that the reflection\n"
2125 " // gets blackened at edges due to leaving the area that contains actual\n"
2127 " // Remove this 'ack once we have a better way to stop this thing from\n"
2129 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2130 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2131 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2132 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2133 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2134 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2135 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2136 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2137 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2138 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2139 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2140 " gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2143 "#else // !MODE_WATER\n"
2148 "// 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"
2150 "// fragment shader specific:\n"
2151 "#ifdef FRAGMENT_SHADER\n"
2154 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2157 "#ifdef USEFOGOUTSIDE\n"
2158 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2160 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2162 " return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2166 "#ifdef USEOFFSETMAPPING\n"
2167 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2169 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2170 " // 14 sample relief mapping: linear search and then binary search\n"
2171 " // this basically steps forward a small amount repeatedly until it finds\n"
2172 " // itself inside solid, then jitters forward and back using decreasing\n"
2173 " // amounts to find the impact\n"
2174 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2175 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2176 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2177 " float3 RT = float3(TexCoord, 1);\n"
2178 " OffsetVector *= 0.1;\n"
2179 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2180 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2181 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2182 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2183 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2184 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2185 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2186 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2187 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2188 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2189 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2190 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2191 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2192 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2195 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2196 " // this basically moves forward the full distance, and then backs up based\n"
2197 " // on height of samples\n"
2198 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2199 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2200 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2201 " TexCoord += OffsetVector;\n"
2202 " OffsetVector *= 0.333;\n"
2203 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2204 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2205 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2206 " return TexCoord;\n"
2209 "#endif // USEOFFSETMAPPING\n"
2211 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2212 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2213 "# ifdef USESHADOWMAPORTHO\n"
2214 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2216 "# ifdef USESHADOWMAPVSDCT\n"
2217 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2219 " float3 adir = abs(dir);\n"
2220 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2221 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2222 " return float3(lerp(dir.xy, proj.xy, dir.zz) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2225 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2227 " float3 adir = abs(dir);\n"
2228 " float ma = adir.z;\n"
2229 " float4 proj = float4(dir, 2.5);\n"
2230 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2231 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2232 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2233 " return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2237 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
2239 "#ifdef USESHADOWMAPCUBE\n"
2240 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2242 " float3 adir = abs(dir);\n"
2243 " return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2247 "# ifdef USESHADOWMAPRECT\n"
2248 "#ifdef USESHADOWMAPVSDCT\n"
2249 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2251 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2254 "#ifdef USESHADOWMAPVSDCT\n"
2255 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2257 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2260 "# ifdef USESHADOWSAMPLER\n"
2262 "# ifdef USESHADOWMAPPCF\n"
2263 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2264 " 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"
2266 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2271 "# ifdef USESHADOWMAPPCF\n"
2272 "# if USESHADOWMAPPCF > 1\n"
2273 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2274 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2275 " 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"
2276 " 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"
2277 " 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"
2278 " 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"
2279 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2280 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2282 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2283 " float2 offset = frac(shadowmaptc.xy);\n"
2284 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2285 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2286 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2287 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2288 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2291 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2295 "# ifdef USESHADOWMAPORTHO\n"
2296 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2303 "# ifdef USESHADOWMAP2D\n"
2304 "#ifdef USESHADOWMAPVSDCT\n"
2305 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2307 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2310 "#ifdef USESHADOWMAPVSDCT\n"
2311 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2313 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2317 "# ifdef USESHADOWSAMPLER\n"
2318 "# ifdef USESHADOWMAPPCF\n"
2319 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
2320 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2321 " 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"
2323 " f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2326 "# ifdef USESHADOWMAPPCF\n"
2327 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2328 "# ifdef GL_ARB_texture_gather\n"
2329 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
2331 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2333 " float2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2334 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2335 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2336 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2337 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2338 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2339 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2340 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2342 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale) \n"
2343 "# if USESHADOWMAPPCF > 1\n"
2344 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2345 " center *= ShadowMap_TextureScale;\n"
2346 " 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"
2347 " 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"
2348 " 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"
2349 " 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"
2350 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2351 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2353 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2354 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2355 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2356 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2357 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2358 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2362 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2365 "# ifdef USESHADOWMAPORTHO\n"
2366 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2373 "# ifdef USESHADOWMAPCUBE\n"
2374 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2376 " // apply depth texture cubemap as light filter\n"
2377 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2379 "# ifdef USESHADOWSAMPLER\n"
2380 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2382 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2387 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2388 "#endif // FRAGMENT_SHADER\n"
2393 "#ifdef MODE_DEFERREDGEOMETRY\n"
2394 "#ifdef VERTEX_SHADER\n"
2397 "float4 gl_Vertex : POSITION,\n"
2398 "uniform float4x4 ModelViewProjectionMatrix,\n"
2399 "#ifdef USEVERTEXTEXTUREBLEND\n"
2400 "float4 gl_Color : COLOR0,\n"
2402 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2403 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2404 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2405 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2406 "uniform float4x4 TexMatrix,\n"
2407 "#ifdef USEVERTEXTEXTUREBLEND\n"
2408 "uniform float4x4 BackgroundTexMatrix,\n"
2410 "uniform float4x4 ModelViewMatrix,\n"
2411 "#ifdef USEOFFSETMAPPING\n"
2412 "uniform float3 EyePosition,\n"
2414 "out float4 gl_Position : POSITION,\n"
2415 "out float4 gl_FrontColor : COLOR,\n"
2416 "out float4 TexCoordBoth : TEXCOORD0,\n"
2417 "#ifdef USEOFFSETMAPPING\n"
2418 "out float3 EyeVector : TEXCOORD2,\n"
2420 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2421 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2422 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2425 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2426 "#ifdef USEVERTEXTEXTUREBLEND\n"
2427 " gl_FrontColor = gl_Color;\n"
2428 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2431 " // transform unnormalized eye direction into tangent space\n"
2432 "#ifdef USEOFFSETMAPPING\n"
2433 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2434 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2435 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2436 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2439 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2440 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2441 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2442 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2444 "#endif // VERTEX_SHADER\n"
2446 "#ifdef FRAGMENT_SHADER\n"
2449 "float4 TexCoordBoth : TEXCOORD0,\n"
2450 "float3 EyeVector : TEXCOORD2,\n"
2451 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2452 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2453 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2454 "uniform sampler2D Texture_Normal,\n"
2455 "#ifdef USEALPHAKILL\n"
2456 "uniform sampler2D Texture_Color,\n"
2458 "uniform sampler2D Texture_Gloss,\n"
2459 "#ifdef USEVERTEXTEXTUREBLEND\n"
2460 "uniform sampler2D Texture_SecondaryNormal,\n"
2461 "uniform sampler2D Texture_SecondaryGloss,\n"
2463 "#ifdef USEOFFSETMAPPING\n"
2464 "uniform float OffsetMapping_Scale,\n"
2466 "uniform half SpecularPower,\n"
2467 "out float4 gl_FragColor : COLOR\n"
2470 " float2 TexCoord = TexCoordBoth.xy;\n"
2471 "#ifdef USEOFFSETMAPPING\n"
2472 " // apply offsetmapping\n"
2473 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2474 "#define TexCoord TexCoordOffset\n"
2477 "#ifdef USEALPHAKILL\n"
2478 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2482 "#ifdef USEVERTEXTEXTUREBLEND\n"
2483 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2484 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2485 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2486 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2489 "#ifdef USEVERTEXTEXTUREBLEND\n"
2490 " float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2491 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2493 " float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2494 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2497 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2499 "#endif // FRAGMENT_SHADER\n"
2500 "#else // !MODE_DEFERREDGEOMETRY\n"
2505 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2506 "#ifdef VERTEX_SHADER\n"
2509 "float4 gl_Vertex : POSITION,\n"
2510 "uniform float4x4 ModelViewProjectionMatrix,\n"
2511 "uniform float4x4 ModelViewMatrix,\n"
2512 "out float4 gl_Position : POSITION,\n"
2513 "out float4 ModelViewPosition : TEXCOORD0\n"
2516 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2517 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2519 "#endif // VERTEX_SHADER\n"
2521 "#ifdef FRAGMENT_SHADER\n"
2524 "float2 Pixel : WPOS,\n"
2525 "float4 ModelViewPosition : TEXCOORD0,\n"
2526 "uniform float4x4 ViewToLight,\n"
2527 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2528 "uniform float3 LightPosition,\n"
2529 "uniform half2 PixelToScreenTexCoord,\n"
2530 "uniform half3 DeferredColor_Ambient,\n"
2531 "uniform half3 DeferredColor_Diffuse,\n"
2532 "#ifdef USESPECULAR\n"
2533 "uniform half3 DeferredColor_Specular,\n"
2534 "uniform half SpecularPower,\n"
2536 "uniform sampler2D Texture_Attenuation,\n"
2537 "uniform sampler2D Texture_ScreenDepth,\n"
2538 "uniform sampler2D Texture_ScreenNormalMap,\n"
2540 "#ifdef USESHADOWMAPRECT\n"
2541 "# ifdef USESHADOWSAMPLER\n"
2542 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2544 "uniform samplerRECT Texture_ShadowMapRect,\n"
2548 "#ifdef USESHADOWMAP2D\n"
2549 "# ifdef USESHADOWSAMPLER\n"
2550 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2552 "uniform sampler2D Texture_ShadowMap2D,\n"
2556 "#ifdef USESHADOWMAPVSDCT\n"
2557 "uniform samplerCUBE Texture_CubeProjection,\n"
2560 "#ifdef USESHADOWMAPCUBE\n"
2561 "# ifdef USESHADOWSAMPLER\n"
2562 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2564 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2568 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2569 "uniform float2 ShadowMap_TextureScale,\n"
2570 "uniform float4 ShadowMap_Parameters,\n"
2573 "out float4 gl_FragData0 : COLOR0,\n"
2574 "out float4 gl_FragData1 : COLOR1\n"
2577 " // calculate viewspace pixel position\n"
2578 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2579 " ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2580 " float3 position;\n"
2581 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2582 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2583 " // decode viewspace pixel normal\n"
2584 " half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2585 " half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2586 " // surfacenormal = pixel normal in viewspace\n"
2587 " // LightVector = pixel to light in viewspace\n"
2588 " // CubeVector = position in lightspace\n"
2589 " // eyevector = pixel to view in viewspace\n"
2590 " float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2591 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2592 "#ifdef USEDIFFUSE\n"
2593 " // calculate diffuse shading\n"
2594 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2595 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2597 "#ifdef USESPECULAR\n"
2598 " // calculate directional shading\n"
2599 " float3 eyevector = position * -1.0;\n"
2600 "# ifdef USEEXACTSPECULARMATH\n"
2601 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2603 " half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2604 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2608 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2609 " fade *= ShadowMapCompare(CubeVector,\n"
2610 "# if defined(USESHADOWMAP2D)\n"
2611 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2613 "# if defined(USESHADOWMAPRECT)\n"
2614 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2616 "# if defined(USESHADOWMAPCUBE)\n"
2617 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2620 "#ifdef USESHADOWMAPVSDCT\n"
2621 ", Texture_CubeProjection\n"
2626 "#ifdef USEDIFFUSE\n"
2627 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2629 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2631 "#ifdef USESPECULAR\n"
2632 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2634 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2637 "# ifdef USECUBEFILTER\n"
2638 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2639 " gl_FragData0.rgb *= cubecolor;\n"
2640 " gl_FragData1.rgb *= cubecolor;\n"
2643 "#endif // FRAGMENT_SHADER\n"
2644 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2649 "#ifdef VERTEX_SHADER\n"
2652 "float4 gl_Vertex : POSITION,\n"
2653 "uniform float4x4 ModelViewProjectionMatrix,\n"
2654 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2655 "float4 gl_Color : COLOR0,\n"
2657 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2658 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2659 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2660 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2661 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2663 "uniform float3 EyePosition,\n"
2664 "uniform float4x4 TexMatrix,\n"
2665 "#ifdef USEVERTEXTEXTUREBLEND\n"
2666 "uniform float4x4 BackgroundTexMatrix,\n"
2668 "#ifdef MODE_LIGHTSOURCE\n"
2669 "uniform float4x4 ModelToLight,\n"
2671 "#ifdef MODE_LIGHTSOURCE\n"
2672 "uniform float3 LightPosition,\n"
2674 "#ifdef MODE_LIGHTDIRECTION\n"
2675 "uniform float3 LightDir,\n"
2677 "uniform float4 FogPlane,\n"
2678 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2679 "uniform float3 LightPosition,\n"
2681 "#ifdef USESHADOWMAPORTHO\n"
2682 "uniform float4x4 ShadowMapMatrix,\n"
2685 "out float4 gl_FrontColor : COLOR,\n"
2686 "out float4 TexCoordBoth : TEXCOORD0,\n"
2687 "#ifdef USELIGHTMAP\n"
2688 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2690 "#ifdef USEEYEVECTOR\n"
2691 "out float3 EyeVector : TEXCOORD2,\n"
2693 "#ifdef USEREFLECTION\n"
2694 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2697 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2699 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2700 "out float3 LightVector : TEXCOORD1,\n"
2702 "#ifdef MODE_LIGHTSOURCE\n"
2703 "out float3 CubeVector : TEXCOORD3,\n"
2705 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2706 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2707 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2708 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2710 "#ifdef USESHADOWMAPORTHO\n"
2711 "out float3 ShadowMapTC : TEXCOORD8,\n"
2713 "out float4 gl_Position : POSITION\n"
2716 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2717 " gl_FrontColor = gl_Color;\n"
2719 " // copy the surface texcoord\n"
2720 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2721 "#ifdef USEVERTEXTEXTUREBLEND\n"
2722 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2724 "#ifdef USELIGHTMAP\n"
2725 " TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2728 "#ifdef MODE_LIGHTSOURCE\n"
2729 " // transform vertex position into light attenuation/cubemap space\n"
2730 " // (-1 to +1 across the light box)\n"
2731 " CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2733 "# ifdef USEDIFFUSE\n"
2734 " // transform unnormalized light direction into tangent space\n"
2735 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2736 " // normalize it per pixel)\n"
2737 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2738 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2739 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2740 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2744 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2745 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2746 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2747 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2750 " // transform unnormalized eye direction into tangent space\n"
2751 "#ifdef USEEYEVECTOR\n"
2752 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2753 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2754 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2755 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2759 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2760 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2763 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2764 " VectorS = gl_MultiTexCoord1.xyz;\n"
2765 " VectorT = gl_MultiTexCoord2.xyz;\n"
2766 " VectorR = gl_MultiTexCoord3.xyz;\n"
2769 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2770 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2772 "#ifdef USESHADOWMAPORTHO\n"
2773 " ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2776 "#ifdef USEREFLECTION\n"
2777 " ModelViewProjectionPosition = gl_Position;\n"
2780 "#endif // VERTEX_SHADER\n"
2785 "#ifdef FRAGMENT_SHADER\n"
2788 "#ifdef USEDEFERREDLIGHTMAP\n"
2789 "float2 Pixel : WPOS,\n"
2791 "float4 gl_FrontColor : COLOR,\n"
2792 "float4 TexCoordBoth : TEXCOORD0,\n"
2793 "#ifdef USELIGHTMAP\n"
2794 "float2 TexCoordLightmap : TEXCOORD1,\n"
2796 "#ifdef USEEYEVECTOR\n"
2797 "float3 EyeVector : TEXCOORD2,\n"
2799 "#ifdef USEREFLECTION\n"
2800 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2803 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2805 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2806 "float3 LightVector : TEXCOORD1,\n"
2808 "#ifdef MODE_LIGHTSOURCE\n"
2809 "float3 CubeVector : TEXCOORD3,\n"
2811 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2812 "float4 ModelViewPosition : TEXCOORD0,\n"
2814 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2815 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2816 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2817 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2819 "#ifdef USESHADOWMAPORTHO\n"
2820 "float3 ShadowMapTC : TEXCOORD8,\n"
2823 "uniform sampler2D Texture_Normal,\n"
2824 "uniform sampler2D Texture_Color,\n"
2825 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2826 "uniform sampler2D Texture_Gloss,\n"
2829 "uniform sampler2D Texture_Glow,\n"
2831 "#ifdef USEVERTEXTEXTUREBLEND\n"
2832 "uniform sampler2D Texture_SecondaryNormal,\n"
2833 "uniform sampler2D Texture_SecondaryColor,\n"
2834 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2835 "uniform sampler2D Texture_SecondaryGloss,\n"
2838 "uniform sampler2D Texture_SecondaryGlow,\n"
2841 "#ifdef USECOLORMAPPING\n"
2842 "uniform sampler2D Texture_Pants,\n"
2843 "uniform sampler2D Texture_Shirt,\n"
2846 "uniform sampler2D Texture_FogMask,\n"
2848 "#ifdef USELIGHTMAP\n"
2849 "uniform sampler2D Texture_Lightmap,\n"
2851 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2852 "uniform sampler2D Texture_Deluxemap,\n"
2854 "#ifdef USEREFLECTION\n"
2855 "uniform sampler2D Texture_Reflection,\n"
2858 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2859 "uniform sampler2D Texture_ScreenDepth,\n"
2860 "uniform sampler2D Texture_ScreenNormalMap,\n"
2862 "#ifdef USEDEFERREDLIGHTMAP\n"
2863 "uniform sampler2D Texture_ScreenDiffuse,\n"
2864 "uniform sampler2D Texture_ScreenSpecular,\n"
2867 "#ifdef USECOLORMAPPING\n"
2868 "uniform half3 Color_Pants,\n"
2869 "uniform half3 Color_Shirt,\n"
2872 "uniform float3 FogColor,\n"
2873 "uniform float FogRangeRecip,\n"
2874 "uniform float FogPlaneViewDist,\n"
2875 "uniform float FogHeightFade,\n"
2878 "#ifdef USEOFFSETMAPPING\n"
2879 "uniform float OffsetMapping_Scale,\n"
2882 "#ifdef USEDEFERREDLIGHTMAP\n"
2883 "uniform half2 PixelToScreenTexCoord,\n"
2884 "uniform half3 DeferredMod_Diffuse,\n"
2885 "uniform half3 DeferredMod_Specular,\n"
2887 "uniform half3 Color_Ambient,\n"
2888 "uniform half3 Color_Diffuse,\n"
2889 "uniform half3 Color_Specular,\n"
2890 "uniform half SpecularPower,\n"
2892 "uniform half3 Color_Glow,\n"
2894 "uniform half Alpha,\n"
2895 "#ifdef USEREFLECTION\n"
2896 "uniform float4 DistortScaleRefractReflect,\n"
2897 "uniform float4 ScreenScaleRefractReflect,\n"
2898 "uniform float4 ScreenCenterRefractReflect,\n"
2899 "uniform half4 ReflectColor,\n"
2901 "#ifdef USEREFLECTCUBE\n"
2902 "uniform float4x4 ModelToReflectCube,\n"
2903 "uniform sampler2D Texture_ReflectMask,\n"
2904 "uniform samplerCUBE Texture_ReflectCube,\n"
2906 "#ifdef MODE_LIGHTDIRECTION\n"
2907 "uniform half3 LightColor,\n"
2909 "#ifdef MODE_LIGHTSOURCE\n"
2910 "uniform half3 LightColor,\n"
2913 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2914 "uniform sampler2D Texture_Attenuation,\n"
2915 "uniform samplerCUBE Texture_Cube,\n"
2918 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2920 "#ifdef USESHADOWMAPRECT\n"
2921 "# ifdef USESHADOWSAMPLER\n"
2922 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2924 "uniform samplerRECT Texture_ShadowMapRect,\n"
2928 "#ifdef USESHADOWMAP2D\n"
2929 "# ifdef USESHADOWSAMPLER\n"
2930 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2932 "uniform sampler2D Texture_ShadowMap2D,\n"
2936 "#ifdef USESHADOWMAPVSDCT\n"
2937 "uniform samplerCUBE Texture_CubeProjection,\n"
2940 "#ifdef USESHADOWMAPCUBE\n"
2941 "# ifdef USESHADOWSAMPLER\n"
2942 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2944 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2948 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2949 "uniform float2 ShadowMap_TextureScale,\n"
2950 "uniform float4 ShadowMap_Parameters,\n"
2952 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2954 "out float4 gl_FragColor : COLOR\n"
2957 " float2 TexCoord = TexCoordBoth.xy;\n"
2958 "#ifdef USEVERTEXTEXTUREBLEND\n"
2959 " float2 TexCoord2 = TexCoordBoth.zw;\n"
2961 "#ifdef USEOFFSETMAPPING\n"
2962 " // apply offsetmapping\n"
2963 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2964 "#define TexCoord TexCoordOffset\n"
2967 " // combine the diffuse textures (base, pants, shirt)\n"
2968 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2969 "#ifdef USEALPHAKILL\n"
2970 " if (color.a < 0.5)\n"
2973 " color.a *= Alpha;\n"
2974 "#ifdef USECOLORMAPPING\n"
2975 " color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2977 "#ifdef USEVERTEXTEXTUREBLEND\n"
2978 " float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2979 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2980 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2981 " color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2983 " //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2986 " // get the surface normal\n"
2987 "#ifdef USEVERTEXTEXTUREBLEND\n"
2988 " half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2990 " half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2993 " // get the material colors\n"
2994 " half3 diffusetex = color.rgb;\n"
2995 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2996 "# ifdef USEVERTEXTEXTUREBLEND\n"
2997 " half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2999 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3003 "#ifdef USEREFLECTCUBE\n"
3004 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3005 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3006 " float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3007 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3013 "#ifdef MODE_LIGHTSOURCE\n"
3014 " // light source\n"
3015 "#ifdef USEDIFFUSE\n"
3016 " half3 lightnormal = half3(normalize(LightVector));\n"
3017 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3018 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3019 "#ifdef USESPECULAR\n"
3020 "#ifdef USEEXACTSPECULARMATH\n"
3021 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3023 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3024 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3026 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3029 " color.rgb = diffusetex * Color_Ambient;\n"
3031 " color.rgb *= LightColor;\n"
3032 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3034 " color.rgb *= ShadowMapCompare(CubeVector,\n"
3035 "# if defined(USESHADOWMAP2D)\n"
3036 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3038 "# if defined(USESHADOWMAPRECT)\n"
3039 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3041 "# if defined(USESHADOWMAPCUBE)\n"
3042 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3045 "#ifdef USESHADOWMAPVSDCT\n"
3046 ", Texture_CubeProjection\n"
3051 "# ifdef USECUBEFILTER\n"
3052 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3054 "#endif // MODE_LIGHTSOURCE\n"
3059 "#ifdef MODE_LIGHTDIRECTION\n"
3061 "#ifdef USEDIFFUSE\n"
3062 " half3 lightnormal = half3(normalize(LightVector));\n"
3064 "#define lightcolor LightColor\n"
3065 "#endif // MODE_LIGHTDIRECTION\n"
3066 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3068 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3069 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3070 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3071 " // convert modelspace light vector to tangentspace\n"
3072 " half3 lightnormal;\n"
3073 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3074 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3075 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3076 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3077 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3078 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3079 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3080 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3081 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3082 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3083 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3084 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3085 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3086 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3087 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3089 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3090 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3091 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3097 "#ifdef MODE_LIGHTMAP\n"
3098 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3099 "#endif // MODE_LIGHTMAP\n"
3100 "#ifdef MODE_VERTEXCOLOR\n"
3101 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3102 "#endif // MODE_VERTEXCOLOR\n"
3103 "#ifdef MODE_FLATCOLOR\n"
3104 " color.rgb = diffusetex * Color_Ambient;\n"
3105 "#endif // MODE_FLATCOLOR\n"
3111 "# ifdef USEDIFFUSE\n"
3112 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3113 "# ifdef USESPECULAR\n"
3114 "# ifdef USEEXACTSPECULARMATH\n"
3115 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3117 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3118 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3120 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3122 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3125 " color.rgb = diffusetex * Color_Ambient;\n"
3129 "#ifdef USESHADOWMAPORTHO\n"
3130 " color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3131 "# if defined(USESHADOWMAP2D)\n"
3132 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3134 "# if defined(USESHADOWMAPRECT)\n"
3135 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3140 "#ifdef USEDEFERREDLIGHTMAP\n"
3141 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3142 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3143 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3147 "#ifdef USEVERTEXTEXTUREBLEND\n"
3148 " color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3150 " color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3155 "#ifdef MODE_LIGHTSOURCE\n"
3156 " color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3158 " color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3162 " // 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"
3163 "#ifdef USEREFLECTION\n"
3164 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3165 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3166 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3167 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3168 " // FIXME temporary hack to detect the case that the reflection\n"
3169 " // gets blackened at edges due to leaving the area that contains actual\n"
3171 " // Remove this 'ack once we have a better way to stop this thing from\n"
3173 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3174 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3175 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3176 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3177 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3178 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3181 " gl_FragColor = float4(color);\n"
3183 "#endif // FRAGMENT_SHADER\n"
3185 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3186 "#endif // !MODE_DEFERREDGEOMETRY\n"
3187 "#endif // !MODE_WATER\n"
3188 "#endif // !MODE_REFRACTION\n"
3189 "#endif // !MODE_BLOOMBLUR\n"
3190 "#endif // !MODE_GENERIC\n"
3191 "#endif // !MODE_POSTPROCESS\n"
3192 "#endif // !MODE_SHOWDEPTH\n"
3193 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3196 char *glslshaderstring = NULL;
3197 char *cgshaderstring = NULL;
3199 //=======================================================================================================================================================
3201 typedef struct shaderpermutationinfo_s
3203 const char *pretext;
3206 shaderpermutationinfo_t;
3208 typedef struct shadermodeinfo_s
3210 const char *vertexfilename;
3211 const char *geometryfilename;
3212 const char *fragmentfilename;
3213 const char *pretext;
3218 typedef enum shaderpermutation_e
3220 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3221 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3222 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3223 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3224 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3225 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3226 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3227 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3228 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3229 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3230 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3231 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3232 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3233 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3234 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3235 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3236 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3237 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3238 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3239 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3240 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3241 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3242 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3243 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3244 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3245 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3246 SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3247 SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3248 SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3249 SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3251 shaderpermutation_t;
3253 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3254 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3256 {"#define USEDIFFUSE\n", " diffuse"},
3257 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3258 {"#define USEVIEWTINT\n", " viewtint"},
3259 {"#define USECOLORMAPPING\n", " colormapping"},
3260 {"#define USESATURATION\n", " saturation"},
3261 {"#define USEFOGINSIDE\n", " foginside"},
3262 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3263 {"#define USEGAMMARAMPS\n", " gammaramps"},
3264 {"#define USECUBEFILTER\n", " cubefilter"},
3265 {"#define USEGLOW\n", " glow"},
3266 {"#define USEBLOOM\n", " bloom"},
3267 {"#define USESPECULAR\n", " specular"},
3268 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3269 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3270 {"#define USEREFLECTION\n", " reflection"},
3271 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3272 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3273 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3274 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3275 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3276 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3277 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3278 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3279 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3280 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3281 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3282 {"#define USEALPHAKILL\n", " alphakill"},
3283 {"#define USEREFLECTCUBE\n", " reflectcube"},
3286 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3287 typedef enum shadermode_e
3289 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3290 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3291 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3292 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3293 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3294 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3295 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3296 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3297 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3298 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3299 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3300 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3301 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3302 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3303 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3308 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3309 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3311 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3312 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3313 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3314 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3315 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3316 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3317 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3318 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3319 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3320 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3321 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3322 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3323 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3324 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3325 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3329 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3331 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3332 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3333 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3334 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3335 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3336 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3337 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3338 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3339 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3340 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3341 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3342 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3343 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3344 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3345 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3349 struct r_glsl_permutation_s;
3350 typedef struct r_glsl_permutation_s
3352 /// hash lookup data
3353 struct r_glsl_permutation_s *hashnext;
3355 unsigned int permutation;
3357 /// indicates if we have tried compiling this permutation already
3359 /// 0 if compilation failed
3361 /// locations of detected uniforms in program object, or -1 if not found
3362 int loc_Texture_First;
3363 int loc_Texture_Second;
3364 int loc_Texture_GammaRamps;
3365 int loc_Texture_Normal;
3366 int loc_Texture_Color;
3367 int loc_Texture_Gloss;
3368 int loc_Texture_Glow;
3369 int loc_Texture_SecondaryNormal;
3370 int loc_Texture_SecondaryColor;
3371 int loc_Texture_SecondaryGloss;
3372 int loc_Texture_SecondaryGlow;
3373 int loc_Texture_Pants;
3374 int loc_Texture_Shirt;
3375 int loc_Texture_FogMask;
3376 int loc_Texture_Lightmap;
3377 int loc_Texture_Deluxemap;
3378 int loc_Texture_Attenuation;
3379 int loc_Texture_Cube;
3380 int loc_Texture_Refraction;
3381 int loc_Texture_Reflection;
3382 int loc_Texture_ShadowMapRect;
3383 int loc_Texture_ShadowMapCube;
3384 int loc_Texture_ShadowMap2D;
3385 int loc_Texture_CubeProjection;
3386 int loc_Texture_ScreenDepth;
3387 int loc_Texture_ScreenNormalMap;
3388 int loc_Texture_ScreenDiffuse;
3389 int loc_Texture_ScreenSpecular;
3390 int loc_Texture_ReflectMask;
3391 int loc_Texture_ReflectCube;
3393 int loc_BloomBlur_Parameters;
3395 int loc_Color_Ambient;
3396 int loc_Color_Diffuse;
3397 int loc_Color_Specular;
3399 int loc_Color_Pants;
3400 int loc_Color_Shirt;
3401 int loc_DeferredColor_Ambient;
3402 int loc_DeferredColor_Diffuse;
3403 int loc_DeferredColor_Specular;
3404 int loc_DeferredMod_Diffuse;
3405 int loc_DeferredMod_Specular;
3406 int loc_DistortScaleRefractReflect;
3407 int loc_EyePosition;
3409 int loc_FogHeightFade;
3411 int loc_FogPlaneViewDist;
3412 int loc_FogRangeRecip;
3415 int loc_LightPosition;
3416 int loc_OffsetMapping_Scale;
3418 int loc_ReflectColor;
3419 int loc_ReflectFactor;
3420 int loc_ReflectOffset;
3421 int loc_RefractColor;
3423 int loc_ScreenCenterRefractReflect;
3424 int loc_ScreenScaleRefractReflect;
3425 int loc_ScreenToDepth;
3426 int loc_ShadowMap_Parameters;
3427 int loc_ShadowMap_TextureScale;
3428 int loc_SpecularPower;
3433 int loc_ViewTintColor;
3434 int loc_ViewToLight;
3435 int loc_ModelToLight;
3437 int loc_BackgroundTexMatrix;
3438 int loc_ModelViewProjectionMatrix;
3439 int loc_ModelViewMatrix;
3440 int loc_PixelToScreenTexCoord;
3441 int loc_ModelToReflectCube;
3442 int loc_ShadowMapMatrix;
3444 r_glsl_permutation_t;
3446 #define SHADERPERMUTATION_HASHSIZE 256
3448 /// information about each possible shader permutation
3449 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3450 /// currently selected permutation
3451 r_glsl_permutation_t *r_glsl_permutation;
3452 /// storage for permutations linked in the hash table
3453 memexpandablearray_t r_glsl_permutationarray;
3455 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3457 //unsigned int hashdepth = 0;
3458 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3459 r_glsl_permutation_t *p;
3460 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3462 if (p->mode == mode && p->permutation == permutation)
3464 //if (hashdepth > 10)
3465 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3470 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3472 p->permutation = permutation;
3473 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3474 r_glsl_permutationhash[mode][hashindex] = p;
3475 //if (hashdepth > 10)
3476 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3480 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3483 if (!filename || !filename[0])
3485 if (!strcmp(filename, "glsl/default.glsl"))
3487 if (!glslshaderstring)
3489 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3490 if (glslshaderstring)
3491 Con_DPrintf("Loading shaders from file %s...\n", filename);
3493 glslshaderstring = (char *)builtinshaderstring;
3495 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3496 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3497 return shaderstring;
3499 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3502 if (printfromdisknotice)
3503 Con_DPrintf("from disk %s... ", filename);
3504 return shaderstring;
3506 return shaderstring;
3509 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3512 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3513 int vertstrings_count = 0;
3514 int geomstrings_count = 0;
3515 int fragstrings_count = 0;
3516 char *vertexstring, *geometrystring, *fragmentstring;
3517 const char *vertstrings_list[32+3];
3518 const char *geomstrings_list[32+3];
3519 const char *fragstrings_list[32+3];
3520 char permutationname[256];
3527 permutationname[0] = 0;
3528 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3529 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3530 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3532 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3534 // the first pretext is which type of shader to compile as
3535 // (later these will all be bound together as a program object)
3536 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3537 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3538 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3540 // the second pretext is the mode (for example a light source)
3541 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3542 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3543 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3544 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3546 // now add all the permutation pretexts
3547 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3549 if (permutation & (1<<i))
3551 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3552 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3553 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3554 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3558 // keep line numbers correct
3559 vertstrings_list[vertstrings_count++] = "\n";
3560 geomstrings_list[geomstrings_count++] = "\n";
3561 fragstrings_list[fragstrings_count++] = "\n";
3565 // now append the shader text itself
3566 vertstrings_list[vertstrings_count++] = vertexstring;
3567 geomstrings_list[geomstrings_count++] = geometrystring;
3568 fragstrings_list[fragstrings_count++] = fragmentstring;
3570 // if any sources were NULL, clear the respective list
3572 vertstrings_count = 0;
3573 if (!geometrystring)
3574 geomstrings_count = 0;
3575 if (!fragmentstring)
3576 fragstrings_count = 0;
3578 // compile the shader program
3579 if (vertstrings_count + geomstrings_count + fragstrings_count)
3580 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3584 qglUseProgramObjectARB(p->program);CHECKGLERROR
3585 // look up all the uniform variable names we care about, so we don't
3586 // have to look them up every time we set them
3588 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3589 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3590 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3591 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3592 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3593 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3594 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3595 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3596 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3597 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3598 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3599 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3600 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3601 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3602 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3603 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3604 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3605 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3606 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3607 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3608 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3609 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3610 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3611 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3612 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3613 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3614 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3615 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3616 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3617 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3618 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3619 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3620 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3621 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3622 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3623 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3624 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3625 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3626 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3627 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3628 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3629 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3630 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3631 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3632 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3633 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3634 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3635 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3636 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3637 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3638 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3639 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3640 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3641 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3642 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3643 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3644 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3645 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3646 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3647 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3648 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3649 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3650 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3651 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3652 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3653 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3654 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3655 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3656 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3657 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3658 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3659 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3660 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3661 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3662 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3663 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3664 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3665 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3666 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3667 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3668 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3669 // initialize the samplers to refer to the texture units we use
3670 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3671 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3672 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3673 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3674 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3675 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3676 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3677 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3678 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3679 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3680 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3681 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3682 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3683 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3684 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3685 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3686 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3687 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3688 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3689 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3690 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3691 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3692 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3693 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3694 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3695 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3696 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3697 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3698 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3699 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3701 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3704 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3708 Mem_Free(vertexstring);
3710 Mem_Free(geometrystring);
3712 Mem_Free(fragmentstring);
3715 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3717 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3718 if (r_glsl_permutation != perm)
3720 r_glsl_permutation = perm;
3721 if (!r_glsl_permutation->program)
3723 if (!r_glsl_permutation->compiled)
3724 R_GLSL_CompilePermutation(perm, mode, permutation);
3725 if (!r_glsl_permutation->program)
3727 // remove features until we find a valid permutation
3729 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3731 // reduce i more quickly whenever it would not remove any bits
3732 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3733 if (!(permutation & j))
3736 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3737 if (!r_glsl_permutation->compiled)
3738 R_GLSL_CompilePermutation(perm, mode, permutation);
3739 if (r_glsl_permutation->program)
3742 if (i >= SHADERPERMUTATION_COUNT)
3744 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3745 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3746 qglUseProgramObjectARB(0);CHECKGLERROR
3747 return; // no bit left to clear, entire mode is broken
3752 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3754 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3755 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3756 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3760 #include <Cg/cgGL.h>
3761 struct r_cg_permutation_s;
3762 typedef struct r_cg_permutation_s
3764 /// hash lookup data
3765 struct r_cg_permutation_s *hashnext;
3767 unsigned int permutation;
3769 /// indicates if we have tried compiling this permutation already
3771 /// 0 if compilation failed
3774 /// locations of detected parameters in programs, or NULL if not found
3775 CGparameter vp_EyePosition;
3776 CGparameter vp_FogPlane;
3777 CGparameter vp_LightDir;
3778 CGparameter vp_LightPosition;
3779 CGparameter vp_ModelToLight;
3780 CGparameter vp_TexMatrix;
3781 CGparameter vp_BackgroundTexMatrix;
3782 CGparameter vp_ModelViewProjectionMatrix;
3783 CGparameter vp_ModelViewMatrix;
3784 CGparameter vp_ShadowMapMatrix;
3786 CGparameter fp_Texture_First;
3787 CGparameter fp_Texture_Second;
3788 CGparameter fp_Texture_GammaRamps;
3789 CGparameter fp_Texture_Normal;
3790 CGparameter fp_Texture_Color;
3791 CGparameter fp_Texture_Gloss;
3792 CGparameter fp_Texture_Glow;
3793 CGparameter fp_Texture_SecondaryNormal;
3794 CGparameter fp_Texture_SecondaryColor;
3795 CGparameter fp_Texture_SecondaryGloss;
3796 CGparameter fp_Texture_SecondaryGlow;
3797 CGparameter fp_Texture_Pants;
3798 CGparameter fp_Texture_Shirt;
3799 CGparameter fp_Texture_FogMask;
3800 CGparameter fp_Texture_Lightmap;
3801 CGparameter fp_Texture_Deluxemap;
3802 CGparameter fp_Texture_Attenuation;
3803 CGparameter fp_Texture_Cube;
3804 CGparameter fp_Texture_Refraction;
3805 CGparameter fp_Texture_Reflection;
3806 CGparameter fp_Texture_ShadowMapRect;
3807 CGparameter fp_Texture_ShadowMapCube;
3808 CGparameter fp_Texture_ShadowMap2D;
3809 CGparameter fp_Texture_CubeProjection;
3810 CGparameter fp_Texture_ScreenDepth;
3811 CGparameter fp_Texture_ScreenNormalMap;
3812 CGparameter fp_Texture_ScreenDiffuse;
3813 CGparameter fp_Texture_ScreenSpecular;
3814 CGparameter fp_Texture_ReflectMask;
3815 CGparameter fp_Texture_ReflectCube;
3816 CGparameter fp_Alpha;
3817 CGparameter fp_BloomBlur_Parameters;
3818 CGparameter fp_ClientTime;
3819 CGparameter fp_Color_Ambient;
3820 CGparameter fp_Color_Diffuse;
3821 CGparameter fp_Color_Specular;
3822 CGparameter fp_Color_Glow;
3823 CGparameter fp_Color_Pants;
3824 CGparameter fp_Color_Shirt;
3825 CGparameter fp_DeferredColor_Ambient;
3826 CGparameter fp_DeferredColor_Diffuse;
3827 CGparameter fp_DeferredColor_Specular;
3828 CGparameter fp_DeferredMod_Diffuse;
3829 CGparameter fp_DeferredMod_Specular;
3830 CGparameter fp_DistortScaleRefractReflect;
3831 CGparameter fp_EyePosition;
3832 CGparameter fp_FogColor;
3833 CGparameter fp_FogHeightFade;
3834 CGparameter fp_FogPlane;
3835 CGparameter fp_FogPlaneViewDist;
3836 CGparameter fp_FogRangeRecip;
3837 CGparameter fp_LightColor;
3838 CGparameter fp_LightDir;
3839 CGparameter fp_LightPosition;
3840 CGparameter fp_OffsetMapping_Scale;
3841 CGparameter fp_PixelSize;
3842 CGparameter fp_ReflectColor;
3843 CGparameter fp_ReflectFactor;
3844 CGparameter fp_ReflectOffset;
3845 CGparameter fp_RefractColor;
3846 CGparameter fp_Saturation;
3847 CGparameter fp_ScreenCenterRefractReflect;
3848 CGparameter fp_ScreenScaleRefractReflect;
3849 CGparameter fp_ScreenToDepth;
3850 CGparameter fp_ShadowMap_Parameters;
3851 CGparameter fp_ShadowMap_TextureScale;
3852 CGparameter fp_SpecularPower;
3853 CGparameter fp_UserVec1;
3854 CGparameter fp_UserVec2;
3855 CGparameter fp_UserVec3;
3856 CGparameter fp_UserVec4;
3857 CGparameter fp_ViewTintColor;
3858 CGparameter fp_ViewToLight;
3859 CGparameter fp_PixelToScreenTexCoord;
3860 CGparameter fp_ModelToReflectCube;
3864 /// information about each possible shader permutation
3865 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3866 /// currently selected permutation
3867 r_cg_permutation_t *r_cg_permutation;
3868 /// storage for permutations linked in the hash table
3869 memexpandablearray_t r_cg_permutationarray;
3871 #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));}}
3873 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3875 //unsigned int hashdepth = 0;
3876 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3877 r_cg_permutation_t *p;
3878 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3880 if (p->mode == mode && p->permutation == permutation)
3882 //if (hashdepth > 10)
3883 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3888 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3890 p->permutation = permutation;
3891 p->hashnext = r_cg_permutationhash[mode][hashindex];
3892 r_cg_permutationhash[mode][hashindex] = p;
3893 //if (hashdepth > 10)
3894 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3898 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3901 if (!filename || !filename[0])
3903 if (!strcmp(filename, "cg/default.cg"))
3905 if (!cgshaderstring)
3907 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3909 Con_DPrintf("Loading shaders from file %s...\n", filename);
3911 cgshaderstring = (char *)builtincgshaderstring;
3913 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3914 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3915 return shaderstring;
3917 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3920 if (printfromdisknotice)
3921 Con_DPrintf("from disk %s... ", filename);
3922 return shaderstring;
3924 return shaderstring;
3927 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3929 // TODO: load or create .fp and .vp shader files
3932 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3935 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3936 int vertstrings_count = 0, vertstring_length = 0;
3937 int geomstrings_count = 0, geomstring_length = 0;
3938 int fragstrings_count = 0, fragstring_length = 0;
3940 char *vertexstring, *geometrystring, *fragmentstring;
3941 char *vertstring, *geomstring, *fragstring;
3942 const char *vertstrings_list[32+3];
3943 const char *geomstrings_list[32+3];
3944 const char *fragstrings_list[32+3];
3945 char permutationname[256];
3946 char cachename[256];
3947 CGprofile vertexProfile;
3948 CGprofile fragmentProfile;
3956 permutationname[0] = 0;
3958 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
3959 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3960 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3962 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3963 strlcat(cachename, "cg/", sizeof(cachename));
3965 // the first pretext is which type of shader to compile as
3966 // (later these will all be bound together as a program object)
3967 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3968 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3969 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3971 // the second pretext is the mode (for example a light source)
3972 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3973 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3974 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3975 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3976 strlcat(cachename, modeinfo->name, sizeof(cachename));
3978 // now add all the permutation pretexts
3979 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3981 if (permutation & (1<<i))
3983 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3984 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3985 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3986 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3987 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
3991 // keep line numbers correct
3992 vertstrings_list[vertstrings_count++] = "\n";
3993 geomstrings_list[geomstrings_count++] = "\n";
3994 fragstrings_list[fragstrings_count++] = "\n";
3998 // replace spaces in the cachename with _ characters
3999 for (i = 0;cachename[i];i++)
4000 if (cachename[i] == ' ')
4003 // now append the shader text itself
4004 vertstrings_list[vertstrings_count++] = vertexstring;
4005 geomstrings_list[geomstrings_count++] = geometrystring;
4006 fragstrings_list[fragstrings_count++] = fragmentstring;
4008 // if any sources were NULL, clear the respective list
4010 vertstrings_count = 0;
4011 if (!geometrystring)
4012 geomstrings_count = 0;
4013 if (!fragmentstring)
4014 fragstrings_count = 0;
4016 vertstring_length = 0;
4017 for (i = 0;i < vertstrings_count;i++)
4018 vertstring_length += strlen(vertstrings_list[i]);
4019 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4020 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4021 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4023 geomstring_length = 0;
4024 for (i = 0;i < geomstrings_count;i++)
4025 geomstring_length += strlen(geomstrings_list[i]);
4026 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4027 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4028 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4030 fragstring_length = 0;
4031 for (i = 0;i < fragstrings_count;i++)
4032 fragstring_length += strlen(fragstrings_list[i]);
4033 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4034 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4035 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4039 //vertexProfile = CG_PROFILE_ARBVP1;
4040 //fragmentProfile = CG_PROFILE_ARBFP1;
4041 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4042 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4043 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4044 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4045 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4048 // try to load the cached shader, or generate one
4049 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4051 // if caching failed, do a dynamic compile for now
4053 if (vertstring[0] && !p->vprogram)
4054 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4056 if (fragstring[0] && !p->fprogram)
4057 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4060 // look up all the uniform variable names we care about, so we don't
4061 // have to look them up every time we set them
4065 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4066 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4067 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4068 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4069 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4070 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4071 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4072 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4073 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4074 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4075 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4076 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4082 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4083 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4084 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4085 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4086 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4087 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4088 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4089 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4090 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4091 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4092 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4093 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4094 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4095 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4096 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4097 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4098 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4099 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4100 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4101 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4102 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4103 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4104 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4105 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4106 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4107 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4108 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4109 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4110 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4111 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4112 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4113 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4114 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4115 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4116 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4117 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4118 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4119 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4120 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4121 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4122 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4123 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4124 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4125 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4126 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4127 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4128 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4129 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4130 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4131 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4132 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4133 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4134 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4135 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4136 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4137 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4138 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4139 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4140 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4141 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4142 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4143 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4144 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4145 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4146 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4147 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4148 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4149 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4150 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4151 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4152 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4153 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4154 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4155 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4156 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4157 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4158 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4162 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4163 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4165 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4169 Mem_Free(vertstring);
4171 Mem_Free(geomstring);
4173 Mem_Free(fragstring);
4175 Mem_Free(vertexstring);
4177 Mem_Free(geometrystring);
4179 Mem_Free(fragmentstring);
4182 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4184 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4187 if (r_cg_permutation != perm)
4189 r_cg_permutation = perm;
4190 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4192 if (!r_cg_permutation->compiled)
4193 R_CG_CompilePermutation(perm, mode, permutation);
4194 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4196 // remove features until we find a valid permutation
4198 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4200 // reduce i more quickly whenever it would not remove any bits
4201 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4202 if (!(permutation & j))
4205 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4206 if (!r_cg_permutation->compiled)
4207 R_CG_CompilePermutation(perm, mode, permutation);
4208 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4211 if (i >= SHADERPERMUTATION_COUNT)
4213 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4214 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4215 return; // no bit left to clear, entire mode is broken
4221 if (r_cg_permutation->vprogram)
4223 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4224 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4225 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4229 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4230 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4232 if (r_cg_permutation->fprogram)
4234 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4235 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4236 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4240 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4241 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4245 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4246 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4247 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4250 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4252 cgGLSetTextureParameter(param, R_GetTexture(tex));
4253 cgGLEnableTextureParameter(param);
4257 void R_GLSL_Restart_f(void)
4259 unsigned int i, limit;
4260 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4261 Mem_Free(glslshaderstring);
4262 glslshaderstring = NULL;
4263 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4264 Mem_Free(cgshaderstring);
4265 cgshaderstring = NULL;
4266 switch(vid.renderpath)
4268 case RENDERPATH_GL20:
4270 r_glsl_permutation_t *p;
4271 r_glsl_permutation = NULL;
4272 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4273 for (i = 0;i < limit;i++)
4275 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4277 GL_Backend_FreeProgram(p->program);
4278 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4281 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4284 case RENDERPATH_CGGL:
4287 r_cg_permutation_t *p;
4288 r_cg_permutation = NULL;
4289 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4290 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4291 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4292 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4293 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4294 for (i = 0;i < limit;i++)
4296 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4299 cgDestroyProgram(p->vprogram);
4301 cgDestroyProgram(p->fprogram);
4302 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4305 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4309 case RENDERPATH_GL13:
4310 case RENDERPATH_GL11:
4315 void R_GLSL_DumpShader_f(void)
4320 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4323 FS_Print(file, "/* The engine may define the following macros:\n");
4324 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4325 for (i = 0;i < SHADERMODE_COUNT;i++)
4326 FS_Print(file, glslshadermodeinfo[i].pretext);
4327 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4328 FS_Print(file, shaderpermutationinfo[i].pretext);
4329 FS_Print(file, "*/\n");
4330 FS_Print(file, builtinshaderstring);
4332 Con_Printf("glsl/default.glsl written\n");
4335 Con_Printf("failed to write to glsl/default.glsl\n");
4338 file = FS_OpenRealFile("cg/default.cg", "w", false);
4341 FS_Print(file, "/* The engine may define the following macros:\n");
4342 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4343 for (i = 0;i < SHADERMODE_COUNT;i++)
4344 FS_Print(file, cgshadermodeinfo[i].pretext);
4345 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4346 FS_Print(file, shaderpermutationinfo[i].pretext);
4347 FS_Print(file, "*/\n");
4348 FS_Print(file, builtincgshaderstring);
4350 Con_Printf("cg/default.cg written\n");
4353 Con_Printf("failed to write to cg/default.cg\n");
4357 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4360 texturemode = GL_MODULATE;
4361 switch (vid.renderpath)
4363 case RENDERPATH_GL20:
4364 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))));
4365 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4366 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4368 case RENDERPATH_CGGL:
4371 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))));
4372 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4373 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4376 case RENDERPATH_GL13:
4377 R_Mesh_TexBind(0, first );
4378 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4379 R_Mesh_TexBind(1, second);
4381 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4383 case RENDERPATH_GL11:
4384 R_Mesh_TexBind(0, first );
4389 void R_SetupShader_DepthOrShadow(void)
4391 switch (vid.renderpath)
4393 case RENDERPATH_GL20:
4394 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4396 case RENDERPATH_CGGL:
4398 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4401 case RENDERPATH_GL13:
4402 R_Mesh_TexBind(0, 0);
4403 R_Mesh_TexBind(1, 0);
4405 case RENDERPATH_GL11:
4406 R_Mesh_TexBind(0, 0);
4411 void R_SetupShader_ShowDepth(void)
4413 switch (vid.renderpath)
4415 case RENDERPATH_GL20:
4416 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4418 case RENDERPATH_CGGL:
4420 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4423 case RENDERPATH_GL13:
4425 case RENDERPATH_GL11:
4430 extern qboolean r_shadow_usingdeferredprepass;
4431 extern cvar_t r_shadow_deferred_8bitrange;
4432 extern rtexture_t *r_shadow_attenuationgradienttexture;
4433 extern rtexture_t *r_shadow_attenuation2dtexture;
4434 extern rtexture_t *r_shadow_attenuation3dtexture;
4435 extern qboolean r_shadow_usingshadowmaprect;
4436 extern qboolean r_shadow_usingshadowmapcube;
4437 extern qboolean r_shadow_usingshadowmap2d;
4438 extern qboolean r_shadow_usingshadowmaportho;
4439 extern float r_shadow_shadowmap_texturescale[2];
4440 extern float r_shadow_shadowmap_parameters[4];
4441 extern qboolean r_shadow_shadowmapvsdct;
4442 extern qboolean r_shadow_shadowmapsampler;
4443 extern int r_shadow_shadowmappcf;
4444 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4445 extern rtexture_t *r_shadow_shadowmap2dtexture;
4446 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4447 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4448 extern matrix4x4_t r_shadow_shadowmapmatrix;
4449 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4450 extern int r_shadow_prepass_width;
4451 extern int r_shadow_prepass_height;
4452 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4453 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4454 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4455 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4456 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4458 // select a permutation of the lighting shader appropriate to this
4459 // combination of texture, entity, light source, and fogging, only use the
4460 // minimum features necessary to avoid wasting rendering time in the
4461 // fragment shader on features that are not being used
4462 unsigned int permutation = 0;
4463 unsigned int mode = 0;
4465 if (rsurfacepass == RSURFPASS_BACKGROUND)
4467 // distorted background
4468 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4469 mode = SHADERMODE_WATER;
4471 mode = SHADERMODE_REFRACTION;
4472 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4473 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4474 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4475 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4476 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4477 R_Mesh_ColorPointer(NULL, 0, 0);
4478 GL_AlphaTest(false);
4479 GL_BlendFunc(GL_ONE, GL_ZERO);
4481 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4483 if (r_glsl_offsetmapping.integer)
4485 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4486 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4487 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4488 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4489 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4491 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4492 if (r_glsl_offsetmapping_reliefmapping.integer)
4493 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4496 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4497 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4498 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4499 permutation |= SHADERPERMUTATION_ALPHAKILL;
4500 // normalmap (deferred prepass), may use alpha test on diffuse
4501 mode = SHADERMODE_DEFERREDGEOMETRY;
4502 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4503 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4504 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4505 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4506 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4507 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4508 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4509 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4510 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4512 R_Mesh_ColorPointer(NULL, 0, 0);
4513 GL_AlphaTest(false);
4514 GL_BlendFunc(GL_ONE, GL_ZERO);
4516 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4518 if (r_glsl_offsetmapping.integer)
4520 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4521 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4522 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4523 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4524 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4526 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4527 if (r_glsl_offsetmapping_reliefmapping.integer)
4528 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4531 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4532 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4534 mode = SHADERMODE_LIGHTSOURCE;
4535 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4536 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4537 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4538 permutation |= SHADERPERMUTATION_CUBEFILTER;
4539 if (diffusescale > 0)
4540 permutation |= SHADERPERMUTATION_DIFFUSE;
4541 if (specularscale > 0)
4543 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4544 if (r_shadow_glossexact.integer)
4545 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4547 if (r_refdef.fogenabled)
4548 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4549 if (rsurface.texture->colormapping)
4550 permutation |= SHADERPERMUTATION_COLORMAPPING;
4551 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4553 if (r_shadow_usingshadowmaprect)
4554 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4555 if (r_shadow_usingshadowmap2d)
4556 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4557 if (r_shadow_usingshadowmapcube)
4558 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4559 else if(r_shadow_shadowmapvsdct)
4560 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4562 if (r_shadow_shadowmapsampler)
4563 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4564 if (r_shadow_shadowmappcf > 1)
4565 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4566 else if (r_shadow_shadowmappcf)
4567 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4569 if (rsurface.texture->reflectmasktexture)
4570 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4571 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4572 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4574 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4575 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4576 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4580 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4581 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4582 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4584 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4585 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4586 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4588 R_Mesh_ColorPointer(NULL, 0, 0);
4589 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4590 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4592 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4594 if (r_glsl_offsetmapping.integer)
4596 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4597 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4598 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4599 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4600 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4602 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4603 if (r_glsl_offsetmapping_reliefmapping.integer)
4604 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4607 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4608 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4609 // unshaded geometry (fullbright or ambient model lighting)
4610 mode = SHADERMODE_FLATCOLOR;
4611 ambientscale = diffusescale = specularscale = 0;
4612 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4613 permutation |= SHADERPERMUTATION_GLOW;
4614 if (r_refdef.fogenabled)
4615 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4616 if (rsurface.texture->colormapping)
4617 permutation |= SHADERPERMUTATION_COLORMAPPING;
4618 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4620 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4621 if (r_shadow_usingshadowmaprect)
4622 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4623 if (r_shadow_usingshadowmap2d)
4624 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4626 if (r_shadow_shadowmapsampler)
4627 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4628 if (r_shadow_shadowmappcf > 1)
4629 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4630 else if (r_shadow_shadowmappcf)
4631 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4633 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4634 permutation |= SHADERPERMUTATION_REFLECTION;
4635 if (rsurface.texture->reflectmasktexture)
4636 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4637 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4638 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4640 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4641 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4642 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4646 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4647 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4648 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4650 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4651 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4652 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4654 R_Mesh_ColorPointer(NULL, 0, 0);
4655 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4656 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4658 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4660 if (r_glsl_offsetmapping.integer)
4662 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4663 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4664 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4665 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4666 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4668 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4669 if (r_glsl_offsetmapping_reliefmapping.integer)
4670 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4673 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4674 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4675 // directional model lighting
4676 mode = SHADERMODE_LIGHTDIRECTION;
4677 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4678 permutation |= SHADERPERMUTATION_GLOW;
4679 permutation |= SHADERPERMUTATION_DIFFUSE;
4680 if (specularscale > 0)
4682 permutation |= SHADERPERMUTATION_SPECULAR;
4683 if (r_shadow_glossexact.integer)
4684 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4686 if (r_refdef.fogenabled)
4687 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4688 if (rsurface.texture->colormapping)
4689 permutation |= SHADERPERMUTATION_COLORMAPPING;
4690 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4692 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4693 if (r_shadow_usingshadowmaprect)
4694 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4695 if (r_shadow_usingshadowmap2d)
4696 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4698 if (r_shadow_shadowmapsampler)
4699 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4700 if (r_shadow_shadowmappcf > 1)
4701 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4702 else if (r_shadow_shadowmappcf)
4703 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4705 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4706 permutation |= SHADERPERMUTATION_REFLECTION;
4707 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4708 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4709 if (rsurface.texture->reflectmasktexture)
4710 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4711 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4712 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4714 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4715 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4716 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4720 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4721 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4722 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4724 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4725 R_Mesh_ColorPointer(NULL, 0, 0);
4726 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4727 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4729 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4731 if (r_glsl_offsetmapping.integer)
4733 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4734 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4735 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4736 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4737 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4739 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4740 if (r_glsl_offsetmapping_reliefmapping.integer)
4741 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4744 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4745 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4746 // ambient model lighting
4747 mode = SHADERMODE_LIGHTDIRECTION;
4748 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4749 permutation |= SHADERPERMUTATION_GLOW;
4750 if (r_refdef.fogenabled)
4751 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4752 if (rsurface.texture->colormapping)
4753 permutation |= SHADERPERMUTATION_COLORMAPPING;
4754 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4756 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4757 if (r_shadow_usingshadowmaprect)
4758 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4759 if (r_shadow_usingshadowmap2d)
4760 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4762 if (r_shadow_shadowmapsampler)
4763 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4764 if (r_shadow_shadowmappcf > 1)
4765 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4766 else if (r_shadow_shadowmappcf)
4767 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4769 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4770 permutation |= SHADERPERMUTATION_REFLECTION;
4771 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4772 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4773 if (rsurface.texture->reflectmasktexture)
4774 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4775 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4776 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4778 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4779 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4780 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4784 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4785 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4786 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4788 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4789 R_Mesh_ColorPointer(NULL, 0, 0);
4790 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4791 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4795 if (r_glsl_offsetmapping.integer)
4797 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4798 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4799 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4800 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4801 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4803 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4804 if (r_glsl_offsetmapping_reliefmapping.integer)
4805 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4808 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4809 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4811 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4812 permutation |= SHADERPERMUTATION_GLOW;
4813 if (r_refdef.fogenabled)
4814 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4815 if (rsurface.texture->colormapping)
4816 permutation |= SHADERPERMUTATION_COLORMAPPING;
4817 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4819 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4820 if (r_shadow_usingshadowmaprect)
4821 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4822 if (r_shadow_usingshadowmap2d)
4823 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4825 if (r_shadow_shadowmapsampler)
4826 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4827 if (r_shadow_shadowmappcf > 1)
4828 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4829 else if (r_shadow_shadowmappcf)
4830 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4832 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4833 permutation |= SHADERPERMUTATION_REFLECTION;
4834 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4835 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4836 if (rsurface.texture->reflectmasktexture)
4837 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4838 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4840 // deluxemapping (light direction texture)
4841 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4842 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4844 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4845 permutation |= SHADERPERMUTATION_DIFFUSE;
4846 if (specularscale > 0)
4848 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4849 if (r_shadow_glossexact.integer)
4850 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4852 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4853 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4854 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4856 R_Mesh_ColorPointer(NULL, 0, 0);
4858 else if (r_glsl_deluxemapping.integer >= 2)
4860 // fake deluxemapping (uniform light direction in tangentspace)
4861 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4862 permutation |= SHADERPERMUTATION_DIFFUSE;
4863 if (specularscale > 0)
4865 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4866 if (r_shadow_glossexact.integer)
4867 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4869 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4870 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4871 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4873 R_Mesh_ColorPointer(NULL, 0, 0);
4875 else if (rsurface.uselightmaptexture)
4877 // ordinary lightmapping (q1bsp, q3bsp)
4878 mode = SHADERMODE_LIGHTMAP;
4879 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4880 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4881 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4883 R_Mesh_ColorPointer(NULL, 0, 0);
4887 // ordinary vertex coloring (q3bsp)
4888 mode = SHADERMODE_VERTEXCOLOR;
4889 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4890 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4892 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4893 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4895 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4896 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4897 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4901 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4902 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4903 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4905 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4906 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4908 switch(vid.renderpath)
4910 case RENDERPATH_GL20:
4911 R_SetupShader_SetPermutationGLSL(mode, permutation);
4912 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4913 if (mode == SHADERMODE_LIGHTSOURCE)
4915 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4916 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4917 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4918 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);
4919 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);
4920 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);
4922 // additive passes are only darkened by fog, not tinted
4923 if (r_glsl_permutation->loc_FogColor >= 0)
4924 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4925 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4929 if (mode == SHADERMODE_FLATCOLOR)
4931 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4933 else if (mode == SHADERMODE_LIGHTDIRECTION)
4935 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]);
4936 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]);
4937 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);
4938 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);
4939 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);
4940 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]);
4941 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]);
4945 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]);
4946 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]);
4947 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);
4948 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);
4949 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);
4951 // additive passes are only darkened by fog, not tinted
4952 if (r_glsl_permutation->loc_FogColor >= 0)
4954 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4955 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4957 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4959 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);
4960 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]);
4961 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]);
4962 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4963 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4964 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4965 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4966 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4968 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4969 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4970 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
4971 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]);
4972 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]);
4974 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4975 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4976 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4977 if (r_glsl_permutation->loc_Color_Pants >= 0)
4979 if (rsurface.texture->pantstexture)
4980 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4982 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4984 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4986 if (rsurface.texture->shirttexture)
4987 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4989 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4991 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]);
4992 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4993 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4994 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4995 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
4996 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]);
4997 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4999 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5000 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5001 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5002 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5003 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5004 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5005 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5006 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5007 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5008 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5009 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5010 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5011 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5012 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5013 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5014 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5015 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
5016 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap );
5017 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5018 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white );
5019 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white );
5020 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5021 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5022 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5023 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5024 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5026 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5027 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture );
5028 if (rsurface.rtlight)
5030 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5031 if (r_shadow_usingshadowmapcube)
5032 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5033 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5038 case RENDERPATH_CGGL:
5040 R_SetupShader_SetPermutationCG(mode, permutation);
5041 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5042 if (mode == SHADERMODE_LIGHTSOURCE)
5044 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5045 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5049 if (mode == SHADERMODE_LIGHTDIRECTION)
5051 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
5054 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5055 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5056 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5057 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5058 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
5061 if (mode == SHADERMODE_LIGHTSOURCE)
5063 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5064 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5065 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
5066 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
5067 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
5069 // additive passes are only darkened by fog, not tinted
5070 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5071 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5075 if (mode == SHADERMODE_FLATCOLOR)
5077 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5079 else if (mode == SHADERMODE_LIGHTDIRECTION)
5081 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
5082 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
5083 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
5084 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
5085 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
5086 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
5087 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
5091 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
5092 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
5093 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
5094 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
5095 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
5097 // additive passes are only darkened by fog, not tinted
5098 if (r_cg_permutation->fp_FogColor)
5100 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5101 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5103 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5106 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
5107 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
5108 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
5109 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5110 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5111 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5112 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5113 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5115 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
5116 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
5117 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5118 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5119 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5120 if (r_cg_permutation->fp_Color_Pants)
5122 if (rsurface.texture->pantstexture)
5123 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5125 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5128 if (r_cg_permutation->fp_Color_Shirt)
5130 if (rsurface.texture->shirttexture)
5131 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5133 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5136 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
5137 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5138 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5139 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5140 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5141 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
5142 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5144 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
5145 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
5146 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
5147 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
5148 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
5149 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
5150 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
5151 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
5152 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
5153 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
5154 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
5155 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
5156 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
5157 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
5158 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
5159 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
5160 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
5161 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
5162 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5163 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , r_texture_white );CHECKCGERROR
5164 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , r_texture_white );CHECKCGERROR
5165 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5166 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5167 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
5168 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
5169 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5171 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5172 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5173 if (rsurface.rtlight)
5175 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5176 if (r_shadow_usingshadowmapcube)
5177 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5178 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5185 case RENDERPATH_GL13:
5186 case RENDERPATH_GL11:
5191 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5193 // select a permutation of the lighting shader appropriate to this
5194 // combination of texture, entity, light source, and fogging, only use the
5195 // minimum features necessary to avoid wasting rendering time in the
5196 // fragment shader on features that are not being used
5197 unsigned int permutation = 0;
5198 unsigned int mode = 0;
5199 const float *lightcolorbase = rtlight->currentcolor;
5200 float ambientscale = rtlight->ambientscale;
5201 float diffusescale = rtlight->diffusescale;
5202 float specularscale = rtlight->specularscale;
5203 // this is the location of the light in view space
5204 vec3_t viewlightorigin;
5205 // this transforms from view space (camera) to light space (cubemap)
5206 matrix4x4_t viewtolight;
5207 matrix4x4_t lighttoview;
5208 float viewtolight16f[16];
5209 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5211 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5212 if (rtlight->currentcubemap != r_texture_whitecube)
5213 permutation |= SHADERPERMUTATION_CUBEFILTER;
5214 if (diffusescale > 0)
5215 permutation |= SHADERPERMUTATION_DIFFUSE;
5216 if (specularscale > 0)
5218 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5219 if (r_shadow_glossexact.integer)
5220 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5222 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5224 if (r_shadow_usingshadowmaprect)
5225 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5226 if (r_shadow_usingshadowmap2d)
5227 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5228 if (r_shadow_usingshadowmapcube)
5229 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5230 else if(r_shadow_shadowmapvsdct)
5231 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5233 if (r_shadow_shadowmapsampler)
5234 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5235 if (r_shadow_shadowmappcf > 1)
5236 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5237 else if (r_shadow_shadowmappcf)
5238 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5240 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5241 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5242 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5243 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5244 switch(vid.renderpath)
5246 case RENDERPATH_GL20:
5247 R_SetupShader_SetPermutationGLSL(mode, permutation);
5248 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5249 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5250 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);
5251 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);
5252 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);
5253 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]);
5254 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]);
5255 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));
5256 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]);
5257 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5259 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5260 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5261 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5262 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5263 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
5264 if (r_shadow_usingshadowmapcube)
5265 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5266 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5267 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5269 case RENDERPATH_CGGL:
5271 R_SetupShader_SetPermutationCG(mode, permutation);
5272 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5273 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5274 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
5275 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
5276 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
5277 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
5278 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
5279 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
5280 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
5281 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5283 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5284 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5285 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5286 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5287 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5288 if (r_shadow_usingshadowmapcube)
5289 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5290 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5291 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5294 case RENDERPATH_GL13:
5295 case RENDERPATH_GL11:
5300 #define SKINFRAME_HASH 1024
5304 int loadsequence; // incremented each level change
5305 memexpandablearray_t array;
5306 skinframe_t *hash[SKINFRAME_HASH];
5309 r_skinframe_t r_skinframe;
5311 void R_SkinFrame_PrepareForPurge(void)
5313 r_skinframe.loadsequence++;
5314 // wrap it without hitting zero
5315 if (r_skinframe.loadsequence >= 200)
5316 r_skinframe.loadsequence = 1;
5319 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5323 // mark the skinframe as used for the purging code
5324 skinframe->loadsequence = r_skinframe.loadsequence;
5327 void R_SkinFrame_Purge(void)
5331 for (i = 0;i < SKINFRAME_HASH;i++)
5333 for (s = r_skinframe.hash[i];s;s = s->next)
5335 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5337 if (s->merged == s->base)
5339 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5340 R_PurgeTexture(s->stain );s->stain = NULL;
5341 R_PurgeTexture(s->merged);s->merged = NULL;
5342 R_PurgeTexture(s->base );s->base = NULL;
5343 R_PurgeTexture(s->pants );s->pants = NULL;
5344 R_PurgeTexture(s->shirt );s->shirt = NULL;
5345 R_PurgeTexture(s->nmap );s->nmap = NULL;
5346 R_PurgeTexture(s->gloss );s->gloss = NULL;
5347 R_PurgeTexture(s->glow );s->glow = NULL;
5348 R_PurgeTexture(s->fog );s->fog = NULL;
5349 R_PurgeTexture(s->reflect);s->reflect = NULL;
5350 s->loadsequence = 0;
5356 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5358 char basename[MAX_QPATH];
5360 Image_StripImageExtension(name, basename, sizeof(basename));
5362 if( last == NULL ) {
5364 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5365 item = r_skinframe.hash[hashindex];
5370 // linearly search through the hash bucket
5371 for( ; item ; item = item->next ) {
5372 if( !strcmp( item->basename, basename ) ) {
5379 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5383 char basename[MAX_QPATH];
5385 Image_StripImageExtension(name, basename, sizeof(basename));
5387 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5388 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5389 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5393 rtexture_t *dyntexture;
5394 // check whether its a dynamic texture
5395 dyntexture = CL_GetDynTexture( basename );
5396 if (!add && !dyntexture)
5398 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5399 memset(item, 0, sizeof(*item));
5400 strlcpy(item->basename, basename, sizeof(item->basename));
5401 item->base = dyntexture; // either NULL or dyntexture handle
5402 item->textureflags = textureflags;
5403 item->comparewidth = comparewidth;
5404 item->compareheight = compareheight;
5405 item->comparecrc = comparecrc;
5406 item->next = r_skinframe.hash[hashindex];
5407 r_skinframe.hash[hashindex] = item;
5409 else if( item->base == NULL )
5411 rtexture_t *dyntexture;
5412 // check whether its a dynamic texture
5413 // 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]
5414 dyntexture = CL_GetDynTexture( basename );
5415 item->base = dyntexture; // either NULL or dyntexture handle
5418 R_SkinFrame_MarkUsed(item);
5422 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5424 unsigned long long avgcolor[5], wsum; \
5432 for(pix = 0; pix < cnt; ++pix) \
5435 for(comp = 0; comp < 3; ++comp) \
5437 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5440 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5442 for(comp = 0; comp < 3; ++comp) \
5443 avgcolor[comp] += getpixel * w; \
5446 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5447 avgcolor[4] += getpixel; \
5449 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5451 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5452 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5453 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5454 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5457 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5460 unsigned char *pixels;
5461 unsigned char *bumppixels;
5462 unsigned char *basepixels = NULL;
5463 int basepixels_width = 0;
5464 int basepixels_height = 0;
5465 skinframe_t *skinframe;
5466 rtexture_t *ddsbase = NULL;
5467 qboolean ddshasalpha = false;
5468 float ddsavgcolor[4];
5469 char basename[MAX_QPATH];
5471 if (cls.state == ca_dedicated)
5474 // return an existing skinframe if already loaded
5475 // if loading of the first image fails, don't make a new skinframe as it
5476 // would cause all future lookups of this to be missing
5477 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5478 if (skinframe && skinframe->base)
5481 Image_StripImageExtension(name, basename, sizeof(basename));
5483 // check for DDS texture file first
5484 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5486 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5487 if (basepixels == NULL)
5491 if (developer_loading.integer)
5492 Con_Printf("loading skin \"%s\"\n", name);
5494 // we've got some pixels to store, so really allocate this new texture now
5496 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5497 skinframe->stain = NULL;
5498 skinframe->merged = NULL;
5499 skinframe->base = NULL;
5500 skinframe->pants = NULL;
5501 skinframe->shirt = NULL;
5502 skinframe->nmap = NULL;
5503 skinframe->gloss = NULL;
5504 skinframe->glow = NULL;
5505 skinframe->fog = NULL;
5506 skinframe->reflect = NULL;
5507 skinframe->hasalpha = false;
5511 skinframe->base = ddsbase;
5512 skinframe->hasalpha = ddshasalpha;
5513 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5514 if (r_loadfog && skinframe->hasalpha)
5515 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5516 //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]);
5520 basepixels_width = image_width;
5521 basepixels_height = image_height;
5522 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);
5523 if (textureflags & TEXF_ALPHA)
5525 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5527 if (basepixels[j] < 255)
5529 skinframe->hasalpha = true;
5533 if (r_loadfog && skinframe->hasalpha)
5535 // has transparent pixels
5536 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5537 for (j = 0;j < image_width * image_height * 4;j += 4)
5542 pixels[j+3] = basepixels[j+3];
5544 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);
5548 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5549 //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]);
5550 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5551 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5552 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5553 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5558 if (r_loadnormalmap)
5559 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5560 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5562 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5563 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5564 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5565 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5568 // _norm is the name used by tenebrae and has been adopted as standard
5569 if (r_loadnormalmap && skinframe->nmap == NULL)
5571 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5573 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);
5577 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5579 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5580 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5581 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);
5583 Mem_Free(bumppixels);
5585 else if (r_shadow_bumpscale_basetexture.value > 0)
5587 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5588 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5589 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);
5592 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5593 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5596 // _luma is supported only for tenebrae compatibility
5597 // _glow is the preferred name
5598 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))))
5600 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);
5601 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5602 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5603 Mem_Free(pixels);pixels = NULL;
5606 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5608 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);
5609 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5610 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5615 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5617 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);
5618 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5619 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5624 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5626 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);
5627 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5628 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5633 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5635 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);
5636 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5637 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5643 Mem_Free(basepixels);
5648 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5649 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5652 unsigned char *temp1, *temp2;
5653 skinframe_t *skinframe;
5655 if (cls.state == ca_dedicated)
5658 // if already loaded just return it, otherwise make a new skinframe
5659 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5660 if (skinframe && skinframe->base)
5663 skinframe->stain = NULL;
5664 skinframe->merged = NULL;
5665 skinframe->base = NULL;
5666 skinframe->pants = NULL;
5667 skinframe->shirt = NULL;
5668 skinframe->nmap = NULL;
5669 skinframe->gloss = NULL;
5670 skinframe->glow = NULL;
5671 skinframe->fog = NULL;
5672 skinframe->reflect = NULL;
5673 skinframe->hasalpha = false;
5675 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5679 if (developer_loading.integer)
5680 Con_Printf("loading 32bit skin \"%s\"\n", name);
5682 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5684 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5685 temp2 = temp1 + width * height * 4;
5686 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5687 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5690 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5691 if (textureflags & TEXF_ALPHA)
5693 for (i = 3;i < width * height * 4;i += 4)
5695 if (skindata[i] < 255)
5697 skinframe->hasalpha = true;
5701 if (r_loadfog && skinframe->hasalpha)
5703 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5704 memcpy(fogpixels, skindata, width * height * 4);
5705 for (i = 0;i < width * height * 4;i += 4)
5706 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5707 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5708 Mem_Free(fogpixels);
5712 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5713 //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]);
5718 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5722 skinframe_t *skinframe;
5724 if (cls.state == ca_dedicated)
5727 // if already loaded just return it, otherwise make a new skinframe
5728 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5729 if (skinframe && skinframe->base)
5732 skinframe->stain = NULL;
5733 skinframe->merged = NULL;
5734 skinframe->base = NULL;
5735 skinframe->pants = NULL;
5736 skinframe->shirt = NULL;
5737 skinframe->nmap = NULL;
5738 skinframe->gloss = NULL;
5739 skinframe->glow = NULL;
5740 skinframe->fog = NULL;
5741 skinframe->reflect = NULL;
5742 skinframe->hasalpha = false;
5744 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5748 if (developer_loading.integer)
5749 Con_Printf("loading quake skin \"%s\"\n", name);
5751 // 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)
5752 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5753 memcpy(skinframe->qpixels, skindata, width*height);
5754 skinframe->qwidth = width;
5755 skinframe->qheight = height;
5758 for (i = 0;i < width * height;i++)
5759 featuresmask |= palette_featureflags[skindata[i]];
5761 skinframe->hasalpha = false;
5762 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5763 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5764 skinframe->qgeneratemerged = true;
5765 skinframe->qgeneratebase = skinframe->qhascolormapping;
5766 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5768 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5769 //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]);
5774 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5778 unsigned char *skindata;
5780 if (!skinframe->qpixels)
5783 if (!skinframe->qhascolormapping)
5784 colormapped = false;
5788 if (!skinframe->qgeneratebase)
5793 if (!skinframe->qgeneratemerged)
5797 width = skinframe->qwidth;
5798 height = skinframe->qheight;
5799 skindata = skinframe->qpixels;
5801 if (skinframe->qgeneratenmap)
5803 unsigned char *temp1, *temp2;
5804 skinframe->qgeneratenmap = false;
5805 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5806 temp2 = temp1 + width * height * 4;
5807 // use either a custom palette or the quake palette
5808 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5809 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5810 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5814 if (skinframe->qgenerateglow)
5816 skinframe->qgenerateglow = false;
5817 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5822 skinframe->qgeneratebase = false;
5823 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);
5824 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5825 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5829 skinframe->qgeneratemerged = false;
5830 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5833 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5835 Mem_Free(skinframe->qpixels);
5836 skinframe->qpixels = NULL;
5840 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)
5843 skinframe_t *skinframe;
5845 if (cls.state == ca_dedicated)
5848 // if already loaded just return it, otherwise make a new skinframe
5849 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5850 if (skinframe && skinframe->base)
5853 skinframe->stain = NULL;
5854 skinframe->merged = NULL;
5855 skinframe->base = NULL;
5856 skinframe->pants = NULL;
5857 skinframe->shirt = NULL;
5858 skinframe->nmap = NULL;
5859 skinframe->gloss = NULL;
5860 skinframe->glow = NULL;
5861 skinframe->fog = NULL;
5862 skinframe->reflect = NULL;
5863 skinframe->hasalpha = false;
5865 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5869 if (developer_loading.integer)
5870 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5872 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5873 if (textureflags & TEXF_ALPHA)
5875 for (i = 0;i < width * height;i++)
5877 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5879 skinframe->hasalpha = true;
5883 if (r_loadfog && skinframe->hasalpha)
5884 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5887 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5888 //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]);
5893 skinframe_t *R_SkinFrame_LoadMissing(void)
5895 skinframe_t *skinframe;
5897 if (cls.state == ca_dedicated)
5900 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5901 skinframe->stain = NULL;
5902 skinframe->merged = NULL;
5903 skinframe->base = NULL;
5904 skinframe->pants = NULL;
5905 skinframe->shirt = NULL;
5906 skinframe->nmap = NULL;
5907 skinframe->gloss = NULL;
5908 skinframe->glow = NULL;
5909 skinframe->fog = NULL;
5910 skinframe->reflect = NULL;
5911 skinframe->hasalpha = false;
5913 skinframe->avgcolor[0] = rand() / RAND_MAX;
5914 skinframe->avgcolor[1] = rand() / RAND_MAX;
5915 skinframe->avgcolor[2] = rand() / RAND_MAX;
5916 skinframe->avgcolor[3] = 1;
5921 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5922 typedef struct suffixinfo_s
5925 qboolean flipx, flipy, flipdiagonal;
5928 static suffixinfo_t suffix[3][6] =
5931 {"px", false, false, false},
5932 {"nx", false, false, false},
5933 {"py", false, false, false},
5934 {"ny", false, false, false},
5935 {"pz", false, false, false},
5936 {"nz", false, false, false}
5939 {"posx", false, false, false},
5940 {"negx", false, false, false},
5941 {"posy", false, false, false},
5942 {"negy", false, false, false},
5943 {"posz", false, false, false},
5944 {"negz", false, false, false}
5947 {"rt", true, false, true},
5948 {"lf", false, true, true},
5949 {"ft", true, true, false},
5950 {"bk", false, false, false},
5951 {"up", true, false, true},
5952 {"dn", true, false, true}
5956 static int componentorder[4] = {0, 1, 2, 3};
5958 rtexture_t *R_LoadCubemap(const char *basename)
5960 int i, j, cubemapsize;
5961 unsigned char *cubemappixels, *image_buffer;
5962 rtexture_t *cubemaptexture;
5964 // must start 0 so the first loadimagepixels has no requested width/height
5966 cubemappixels = NULL;
5967 cubemaptexture = NULL;
5968 // keep trying different suffix groups (posx, px, rt) until one loads
5969 for (j = 0;j < 3 && !cubemappixels;j++)
5971 // load the 6 images in the suffix group
5972 for (i = 0;i < 6;i++)
5974 // generate an image name based on the base and and suffix
5975 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5977 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
5979 // an image loaded, make sure width and height are equal
5980 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
5982 // if this is the first image to load successfully, allocate the cubemap memory
5983 if (!cubemappixels && image_width >= 1)
5985 cubemapsize = image_width;
5986 // note this clears to black, so unavailable sides are black
5987 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
5989 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
5991 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);
5994 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
5996 Mem_Free(image_buffer);
6000 // if a cubemap loaded, upload it
6003 if (developer_loading.integer)
6004 Con_Printf("loading cubemap \"%s\"\n", basename);
6006 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
6007 Mem_Free(cubemappixels);
6011 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6012 if (developer_loading.integer)
6014 Con_Printf("(tried tried images ");
6015 for (j = 0;j < 3;j++)
6016 for (i = 0;i < 6;i++)
6017 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6018 Con_Print(" and was unable to find any of them).\n");
6021 return cubemaptexture;
6024 rtexture_t *R_GetCubemap(const char *basename)
6027 for (i = 0;i < r_texture_numcubemaps;i++)
6028 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6029 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6030 if (i >= MAX_CUBEMAPS)
6031 return r_texture_whitecube;
6032 r_texture_numcubemaps++;
6033 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6034 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6035 return r_texture_cubemaps[i].texture;
6038 void R_FreeCubemaps(void)
6041 for (i = 0;i < r_texture_numcubemaps;i++)
6043 if (developer_loading.integer)
6044 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6045 if (r_texture_cubemaps[i].texture)
6046 R_FreeTexture(r_texture_cubemaps[i].texture);
6048 r_texture_numcubemaps = 0;
6051 void R_Main_FreeViewCache(void)
6053 if (r_refdef.viewcache.entityvisible)
6054 Mem_Free(r_refdef.viewcache.entityvisible);
6055 if (r_refdef.viewcache.world_pvsbits)
6056 Mem_Free(r_refdef.viewcache.world_pvsbits);
6057 if (r_refdef.viewcache.world_leafvisible)
6058 Mem_Free(r_refdef.viewcache.world_leafvisible);
6059 if (r_refdef.viewcache.world_surfacevisible)
6060 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6061 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6064 void R_Main_ResizeViewCache(void)
6066 int numentities = r_refdef.scene.numentities;
6067 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6068 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6069 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6070 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6071 if (r_refdef.viewcache.maxentities < numentities)
6073 r_refdef.viewcache.maxentities = numentities;
6074 if (r_refdef.viewcache.entityvisible)
6075 Mem_Free(r_refdef.viewcache.entityvisible);
6076 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6078 if (r_refdef.viewcache.world_numclusters != numclusters)
6080 r_refdef.viewcache.world_numclusters = numclusters;
6081 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6082 if (r_refdef.viewcache.world_pvsbits)
6083 Mem_Free(r_refdef.viewcache.world_pvsbits);
6084 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6086 if (r_refdef.viewcache.world_numleafs != numleafs)
6088 r_refdef.viewcache.world_numleafs = numleafs;
6089 if (r_refdef.viewcache.world_leafvisible)
6090 Mem_Free(r_refdef.viewcache.world_leafvisible);
6091 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6093 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6095 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6096 if (r_refdef.viewcache.world_surfacevisible)
6097 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6098 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6102 extern rtexture_t *loadingscreentexture;
6103 void gl_main_start(void)
6105 loadingscreentexture = NULL;
6106 r_texture_blanknormalmap = NULL;
6107 r_texture_white = NULL;
6108 r_texture_grey128 = NULL;
6109 r_texture_black = NULL;
6110 r_texture_whitecube = NULL;
6111 r_texture_normalizationcube = NULL;
6112 r_texture_fogattenuation = NULL;
6113 r_texture_gammaramps = NULL;
6114 r_texture_numcubemaps = 0;
6116 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6117 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6119 switch(vid.renderpath)
6121 case RENDERPATH_GL20:
6122 case RENDERPATH_CGGL:
6123 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6124 Cvar_SetValueQuick(&gl_combine, 1);
6125 Cvar_SetValueQuick(&r_glsl, 1);
6126 r_loadnormalmap = true;
6130 case RENDERPATH_GL13:
6131 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6132 Cvar_SetValueQuick(&gl_combine, 1);
6133 Cvar_SetValueQuick(&r_glsl, 0);
6134 r_loadnormalmap = false;
6135 r_loadgloss = false;
6138 case RENDERPATH_GL11:
6139 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6140 Cvar_SetValueQuick(&gl_combine, 0);
6141 Cvar_SetValueQuick(&r_glsl, 0);
6142 r_loadnormalmap = false;
6143 r_loadgloss = false;
6149 R_FrameData_Reset();
6153 memset(r_queries, 0, sizeof(r_queries));
6155 r_qwskincache = NULL;
6156 r_qwskincache_size = 0;
6158 // set up r_skinframe loading system for textures
6159 memset(&r_skinframe, 0, sizeof(r_skinframe));
6160 r_skinframe.loadsequence = 1;
6161 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6163 r_main_texturepool = R_AllocTexturePool();
6164 R_BuildBlankTextures();
6166 if (vid.support.arb_texture_cube_map)
6169 R_BuildNormalizationCube();
6171 r_texture_fogattenuation = NULL;
6172 r_texture_gammaramps = NULL;
6173 //r_texture_fogintensity = NULL;
6174 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6175 memset(&r_waterstate, 0, sizeof(r_waterstate));
6176 r_glsl_permutation = NULL;
6177 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6178 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6179 glslshaderstring = NULL;
6181 r_cg_permutation = NULL;
6182 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6183 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6184 cgshaderstring = NULL;
6186 memset(&r_svbsp, 0, sizeof (r_svbsp));
6188 r_refdef.fogmasktable_density = 0;
6191 void gl_main_shutdown(void)
6194 R_FrameData_Reset();
6196 R_Main_FreeViewCache();
6199 qglDeleteQueriesARB(r_maxqueries, r_queries);
6203 memset(r_queries, 0, sizeof(r_queries));
6205 r_qwskincache = NULL;
6206 r_qwskincache_size = 0;
6208 // clear out the r_skinframe state
6209 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6210 memset(&r_skinframe, 0, sizeof(r_skinframe));
6213 Mem_Free(r_svbsp.nodes);
6214 memset(&r_svbsp, 0, sizeof (r_svbsp));
6215 R_FreeTexturePool(&r_main_texturepool);
6216 loadingscreentexture = NULL;
6217 r_texture_blanknormalmap = NULL;
6218 r_texture_white = NULL;
6219 r_texture_grey128 = NULL;
6220 r_texture_black = NULL;
6221 r_texture_whitecube = NULL;
6222 r_texture_normalizationcube = NULL;
6223 r_texture_fogattenuation = NULL;
6224 r_texture_gammaramps = NULL;
6225 r_texture_numcubemaps = 0;
6226 //r_texture_fogintensity = NULL;
6227 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6228 memset(&r_waterstate, 0, sizeof(r_waterstate));
6229 r_glsl_permutation = NULL;
6230 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6231 glslshaderstring = NULL;
6233 r_cg_permutation = NULL;
6234 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6235 cgshaderstring = NULL;
6240 extern void CL_ParseEntityLump(char *entitystring);
6241 void gl_main_newmap(void)
6243 // FIXME: move this code to client
6245 char *entities, entname[MAX_QPATH];
6247 Mem_Free(r_qwskincache);
6248 r_qwskincache = NULL;
6249 r_qwskincache_size = 0;
6252 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6253 l = (int)strlen(entname) - 4;
6254 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6256 memcpy(entname + l, ".ent", 5);
6257 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6259 CL_ParseEntityLump(entities);
6264 if (cl.worldmodel->brush.entities)
6265 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6267 R_Main_FreeViewCache();
6269 R_FrameData_Reset();
6272 void GL_Main_Init(void)
6274 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6276 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6277 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6278 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6279 if (gamemode == GAME_NEHAHRA)
6281 Cvar_RegisterVariable (&gl_fogenable);
6282 Cvar_RegisterVariable (&gl_fogdensity);
6283 Cvar_RegisterVariable (&gl_fogred);
6284 Cvar_RegisterVariable (&gl_foggreen);
6285 Cvar_RegisterVariable (&gl_fogblue);
6286 Cvar_RegisterVariable (&gl_fogstart);
6287 Cvar_RegisterVariable (&gl_fogend);
6288 Cvar_RegisterVariable (&gl_skyclip);
6290 Cvar_RegisterVariable(&r_motionblur);
6291 Cvar_RegisterVariable(&r_motionblur_maxblur);
6292 Cvar_RegisterVariable(&r_motionblur_bmin);
6293 Cvar_RegisterVariable(&r_motionblur_vmin);
6294 Cvar_RegisterVariable(&r_motionblur_vmax);
6295 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6296 Cvar_RegisterVariable(&r_motionblur_randomize);
6297 Cvar_RegisterVariable(&r_damageblur);
6298 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6299 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6300 Cvar_RegisterVariable(&r_equalize_entities_by);
6301 Cvar_RegisterVariable(&r_equalize_entities_to);
6302 Cvar_RegisterVariable(&r_depthfirst);
6303 Cvar_RegisterVariable(&r_useinfinitefarclip);
6304 Cvar_RegisterVariable(&r_farclip_base);
6305 Cvar_RegisterVariable(&r_farclip_world);
6306 Cvar_RegisterVariable(&r_nearclip);
6307 Cvar_RegisterVariable(&r_showbboxes);
6308 Cvar_RegisterVariable(&r_showsurfaces);
6309 Cvar_RegisterVariable(&r_showtris);
6310 Cvar_RegisterVariable(&r_shownormals);
6311 Cvar_RegisterVariable(&r_showlighting);
6312 Cvar_RegisterVariable(&r_showshadowvolumes);
6313 Cvar_RegisterVariable(&r_showcollisionbrushes);
6314 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6315 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6316 Cvar_RegisterVariable(&r_showdisabledepthtest);
6317 Cvar_RegisterVariable(&r_drawportals);
6318 Cvar_RegisterVariable(&r_drawentities);
6319 Cvar_RegisterVariable(&r_cullentities_trace);
6320 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6321 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6322 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6323 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6324 Cvar_RegisterVariable(&r_drawviewmodel);
6325 Cvar_RegisterVariable(&r_speeds);
6326 Cvar_RegisterVariable(&r_fullbrights);
6327 Cvar_RegisterVariable(&r_wateralpha);
6328 Cvar_RegisterVariable(&r_dynamic);
6329 Cvar_RegisterVariable(&r_fullbright);
6330 Cvar_RegisterVariable(&r_shadows);
6331 Cvar_RegisterVariable(&r_shadows_darken);
6332 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6333 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6334 Cvar_RegisterVariable(&r_shadows_throwdistance);
6335 Cvar_RegisterVariable(&r_shadows_throwdirection);
6336 Cvar_RegisterVariable(&r_shadows_focus);
6337 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6338 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6339 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6340 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6341 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6342 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6343 Cvar_RegisterVariable(&r_fog_exp2);
6344 Cvar_RegisterVariable(&r_drawfog);
6345 Cvar_RegisterVariable(&r_transparentdepthmasking);
6346 Cvar_RegisterVariable(&r_texture_dds_load);
6347 Cvar_RegisterVariable(&r_texture_dds_save);
6348 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6349 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6350 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6351 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6352 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6353 Cvar_RegisterVariable(&r_textureunits);
6354 Cvar_RegisterVariable(&gl_combine);
6355 Cvar_RegisterVariable(&r_glsl);
6356 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6357 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6358 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6359 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6360 Cvar_RegisterVariable(&r_glsl_postprocess);
6361 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6362 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6363 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6364 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6365 Cvar_RegisterVariable(&r_water);
6366 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6367 Cvar_RegisterVariable(&r_water_clippingplanebias);
6368 Cvar_RegisterVariable(&r_water_refractdistort);
6369 Cvar_RegisterVariable(&r_water_reflectdistort);
6370 Cvar_RegisterVariable(&r_lerpsprites);
6371 Cvar_RegisterVariable(&r_lerpmodels);
6372 Cvar_RegisterVariable(&r_lerplightstyles);
6373 Cvar_RegisterVariable(&r_waterscroll);
6374 Cvar_RegisterVariable(&r_bloom);
6375 Cvar_RegisterVariable(&r_bloom_colorscale);
6376 Cvar_RegisterVariable(&r_bloom_brighten);
6377 Cvar_RegisterVariable(&r_bloom_blur);
6378 Cvar_RegisterVariable(&r_bloom_resolution);
6379 Cvar_RegisterVariable(&r_bloom_colorexponent);
6380 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6381 Cvar_RegisterVariable(&r_hdr);
6382 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6383 Cvar_RegisterVariable(&r_hdr_glowintensity);
6384 Cvar_RegisterVariable(&r_hdr_range);
6385 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6386 Cvar_RegisterVariable(&developer_texturelogging);
6387 Cvar_RegisterVariable(&gl_lightmaps);
6388 Cvar_RegisterVariable(&r_test);
6389 Cvar_RegisterVariable(&r_batchmode);
6390 Cvar_RegisterVariable(&r_glsl_saturation);
6391 Cvar_RegisterVariable(&r_framedatasize);
6392 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6393 Cvar_SetValue("r_fullbrights", 0);
6394 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6396 Cvar_RegisterVariable(&r_track_sprites);
6397 Cvar_RegisterVariable(&r_track_sprites_flags);
6398 Cvar_RegisterVariable(&r_track_sprites_scalew);
6399 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6400 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6401 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6404 extern void R_Textures_Init(void);
6405 extern void GL_Draw_Init(void);
6406 extern void GL_Main_Init(void);
6407 extern void R_Shadow_Init(void);
6408 extern void R_Sky_Init(void);
6409 extern void GL_Surf_Init(void);
6410 extern void R_Particles_Init(void);
6411 extern void R_Explosion_Init(void);
6412 extern void gl_backend_init(void);
6413 extern void Sbar_Init(void);
6414 extern void R_LightningBeams_Init(void);
6415 extern void Mod_RenderInit(void);
6416 extern void Font_Init(void);
6418 void Render_Init(void)
6431 R_LightningBeams_Init();
6440 extern char *ENGINE_EXTENSIONS;
6443 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6444 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6445 gl_version = (const char *)qglGetString(GL_VERSION);
6446 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6450 if (!gl_platformextensions)
6451 gl_platformextensions = "";
6453 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6454 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6455 Con_Printf("GL_VERSION: %s\n", gl_version);
6456 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6457 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6459 VID_CheckExtensions();
6461 // LordHavoc: report supported extensions
6462 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6464 // clear to black (loading plaque will be seen over this)
6466 qglClearColor(0,0,0,1);CHECKGLERROR
6467 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6470 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6474 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6476 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6479 p = r_refdef.view.frustum + i;
6484 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6488 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6492 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6496 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6500 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6504 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6508 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6512 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6520 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6524 for (i = 0;i < numplanes;i++)
6531 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6535 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6539 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6543 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6547 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6551 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6555 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6559 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6567 //==================================================================================
6569 // LordHavoc: this stores temporary data used within the same frame
6571 qboolean r_framedata_failed;
6572 static size_t r_framedata_size;
6573 static size_t r_framedata_current;
6574 static void *r_framedata_base;
6576 void R_FrameData_Reset(void)
6578 if (r_framedata_base)
6579 Mem_Free(r_framedata_base);
6580 r_framedata_base = NULL;
6581 r_framedata_size = 0;
6582 r_framedata_current = 0;
6583 r_framedata_failed = false;
6586 void R_FrameData_NewFrame(void)
6589 if (r_framedata_failed)
6590 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6591 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6592 wantedsize = bound(65536, wantedsize, 128*1024*1024);
6593 if (r_framedata_size != wantedsize)
6595 r_framedata_size = wantedsize;
6596 if (r_framedata_base)
6597 Mem_Free(r_framedata_base);
6598 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6600 r_framedata_current = 0;
6601 r_framedata_failed = false;
6604 void *R_FrameData_Alloc(size_t size)
6608 // align to 16 byte boundary
6609 size = (size + 15) & ~15;
6610 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6611 r_framedata_current += size;
6614 if (r_framedata_current > r_framedata_size)
6615 r_framedata_failed = true;
6617 // return NULL on everything after a failure
6618 if (r_framedata_failed)
6624 void *R_FrameData_Store(size_t size, void *data)
6626 void *d = R_FrameData_Alloc(size);
6628 memcpy(d, data, size);
6632 //==================================================================================
6634 // LordHavoc: animcache originally written by Echon, rewritten since then
6637 * Animation cache prevents re-generating mesh data for an animated model
6638 * multiple times in one frame for lighting, shadowing, reflections, etc.
6641 void R_AnimCache_Free(void)
6645 void R_AnimCache_ClearCache(void)
6648 entity_render_t *ent;
6650 for (i = 0;i < r_refdef.scene.numentities;i++)
6652 ent = r_refdef.scene.entities[i];
6653 ent->animcache_vertex3f = NULL;
6654 ent->animcache_normal3f = NULL;
6655 ent->animcache_svector3f = NULL;
6656 ent->animcache_tvector3f = NULL;
6660 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6662 dp_model_t *model = ent->model;
6664 // see if it's already cached this frame
6665 if (ent->animcache_vertex3f)
6667 // add normals/tangents if needed
6668 if (wantnormals || wanttangents)
6670 if (ent->animcache_normal3f)
6671 wantnormals = false;
6672 if (ent->animcache_svector3f)
6673 wanttangents = false;
6674 if (wantnormals || wanttangents)
6676 numvertices = model->surfmesh.num_vertices;
6678 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6681 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6682 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6684 if (!r_framedata_failed)
6685 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6691 // see if this ent is worth caching
6692 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6694 // get some memory for this entity and generate mesh data
6695 numvertices = model->surfmesh.num_vertices;
6696 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6698 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6701 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6702 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6704 if (!r_framedata_failed)
6705 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6707 return !r_framedata_failed;
6710 void R_AnimCache_CacheVisibleEntities(void)
6713 qboolean wantnormals = !r_showsurfaces.integer;
6714 qboolean wanttangents = !r_showsurfaces.integer;
6716 switch(vid.renderpath)
6718 case RENDERPATH_GL20:
6719 case RENDERPATH_CGGL:
6721 case RENDERPATH_GL13:
6722 case RENDERPATH_GL11:
6723 wanttangents = false;
6727 // TODO: thread this
6728 // NOTE: R_PrepareRTLights() also caches entities
6730 for (i = 0;i < r_refdef.scene.numentities;i++)
6731 if (r_refdef.viewcache.entityvisible[i])
6732 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6735 //==================================================================================
6737 static void R_View_UpdateEntityLighting (void)
6740 entity_render_t *ent;
6741 vec3_t tempdiffusenormal, avg;
6742 vec_t f, fa, fd, fdd;
6743 qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
6745 for (i = 0;i < r_refdef.scene.numentities;i++)
6747 ent = r_refdef.scene.entities[i];
6749 // skip unseen models
6750 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6754 if (ent->model && ent->model->brush.num_leafs)
6756 // TODO: use modellight for r_ambient settings on world?
6757 VectorSet(ent->modellight_ambient, 0, 0, 0);
6758 VectorSet(ent->modellight_diffuse, 0, 0, 0);
6759 VectorSet(ent->modellight_lightdir, 0, 0, 1);
6763 // fetch the lighting from the worldmodel data
6764 VectorClear(ent->modellight_ambient);
6765 VectorClear(ent->modellight_diffuse);
6766 VectorClear(tempdiffusenormal);
6767 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6770 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6771 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6772 if(ent->flags & RENDER_EQUALIZE)
6774 // first fix up ambient lighting...
6775 if(r_equalize_entities_minambient.value > 0)
6777 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6780 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6781 if(fa < r_equalize_entities_minambient.value * fd)
6784 // fa'/fd' = minambient
6785 // fa'+0.25*fd' = fa+0.25*fd
6787 // fa' = fd' * minambient
6788 // fd'*(0.25+minambient) = fa+0.25*fd
6790 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6791 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6793 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6794 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
6795 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6796 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6801 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6803 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6804 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6807 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6808 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6809 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6815 VectorSet(ent->modellight_ambient, 1, 1, 1);
6817 // move the light direction into modelspace coordinates for lighting code
6818 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6819 if(VectorLength2(ent->modellight_lightdir) == 0)
6820 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6821 VectorNormalize(ent->modellight_lightdir);
6825 #define MAX_LINEOFSIGHTTRACES 64
6827 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6830 vec3_t boxmins, boxmaxs;
6833 dp_model_t *model = r_refdef.scene.worldmodel;
6835 if (!model || !model->brush.TraceLineOfSight)
6838 // expand the box a little
6839 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6840 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6841 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6842 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6843 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6844 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6846 // return true if eye is inside enlarged box
6847 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6851 VectorCopy(eye, start);
6852 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6853 if (model->brush.TraceLineOfSight(model, start, end))
6856 // try various random positions
6857 for (i = 0;i < numsamples;i++)
6859 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6860 if (model->brush.TraceLineOfSight(model, start, end))
6868 static void R_View_UpdateEntityVisible (void)
6873 entity_render_t *ent;
6875 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6876 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6877 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
6878 : RENDER_EXTERIORMODEL;
6879 if (!r_drawviewmodel.integer)
6880 renderimask |= RENDER_VIEWMODEL;
6881 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6883 // worldmodel can check visibility
6884 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6885 for (i = 0;i < r_refdef.scene.numentities;i++)
6887 ent = r_refdef.scene.entities[i];
6888 if (!(ent->flags & renderimask))
6889 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)))
6890 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))
6891 r_refdef.viewcache.entityvisible[i] = true;
6893 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6895 for (i = 0;i < r_refdef.scene.numentities;i++)
6897 ent = r_refdef.scene.entities[i];
6898 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6900 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6902 continue; // temp entities do pvs only
6903 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6904 ent->last_trace_visibility = realtime;
6905 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6906 r_refdef.viewcache.entityvisible[i] = 0;
6913 // no worldmodel or it can't check visibility
6914 for (i = 0;i < r_refdef.scene.numentities;i++)
6916 ent = r_refdef.scene.entities[i];
6917 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));
6922 /// only used if skyrendermasked, and normally returns false
6923 int R_DrawBrushModelsSky (void)
6926 entity_render_t *ent;
6929 for (i = 0;i < r_refdef.scene.numentities;i++)
6931 if (!r_refdef.viewcache.entityvisible[i])
6933 ent = r_refdef.scene.entities[i];
6934 if (!ent->model || !ent->model->DrawSky)
6936 ent->model->DrawSky(ent);
6942 static void R_DrawNoModel(entity_render_t *ent);
6943 static void R_DrawModels(void)
6946 entity_render_t *ent;
6948 for (i = 0;i < r_refdef.scene.numentities;i++)
6950 if (!r_refdef.viewcache.entityvisible[i])
6952 ent = r_refdef.scene.entities[i];
6953 r_refdef.stats.entities++;
6954 if (ent->model && ent->model->Draw != NULL)
6955 ent->model->Draw(ent);
6961 static void R_DrawModelsDepth(void)
6964 entity_render_t *ent;
6966 for (i = 0;i < r_refdef.scene.numentities;i++)
6968 if (!r_refdef.viewcache.entityvisible[i])
6970 ent = r_refdef.scene.entities[i];
6971 if (ent->model && ent->model->DrawDepth != NULL)
6972 ent->model->DrawDepth(ent);
6976 static void R_DrawModelsDebug(void)
6979 entity_render_t *ent;
6981 for (i = 0;i < r_refdef.scene.numentities;i++)
6983 if (!r_refdef.viewcache.entityvisible[i])
6985 ent = r_refdef.scene.entities[i];
6986 if (ent->model && ent->model->DrawDebug != NULL)
6987 ent->model->DrawDebug(ent);
6991 static void R_DrawModelsAddWaterPlanes(void)
6994 entity_render_t *ent;
6996 for (i = 0;i < r_refdef.scene.numentities;i++)
6998 if (!r_refdef.viewcache.entityvisible[i])
7000 ent = r_refdef.scene.entities[i];
7001 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7002 ent->model->DrawAddWaterPlanes(ent);
7006 static void R_View_SetFrustum(void)
7009 double slopex, slopey;
7010 vec3_t forward, left, up, origin;
7012 // we can't trust r_refdef.view.forward and friends in reflected scenes
7013 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7016 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7017 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7018 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7019 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7020 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7021 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7022 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7023 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7024 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7025 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7026 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7027 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7031 zNear = r_refdef.nearclip;
7032 nudge = 1.0 - 1.0 / (1<<23);
7033 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7034 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7035 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7036 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7037 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7038 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7039 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7040 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7046 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7047 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7048 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7049 r_refdef.view.frustum[0].dist = m[15] - m[12];
7051 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7052 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7053 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7054 r_refdef.view.frustum[1].dist = m[15] + m[12];
7056 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7057 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7058 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7059 r_refdef.view.frustum[2].dist = m[15] - m[13];
7061 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7062 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7063 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7064 r_refdef.view.frustum[3].dist = m[15] + m[13];
7066 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7067 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7068 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7069 r_refdef.view.frustum[4].dist = m[15] - m[14];
7071 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7072 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7073 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7074 r_refdef.view.frustum[5].dist = m[15] + m[14];
7077 if (r_refdef.view.useperspective)
7079 slopex = 1.0 / r_refdef.view.frustum_x;
7080 slopey = 1.0 / r_refdef.view.frustum_y;
7081 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7082 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
7083 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
7084 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
7085 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7087 // Leaving those out was a mistake, those were in the old code, and they
7088 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7089 // I couldn't reproduce it after adding those normalizations. --blub
7090 VectorNormalize(r_refdef.view.frustum[0].normal);
7091 VectorNormalize(r_refdef.view.frustum[1].normal);
7092 VectorNormalize(r_refdef.view.frustum[2].normal);
7093 VectorNormalize(r_refdef.view.frustum[3].normal);
7095 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7096 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]);
7097 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]);
7098 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]);
7099 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]);
7101 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7102 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7103 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7104 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7105 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7109 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7110 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7111 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7112 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7113 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7114 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7115 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7116 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7117 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7118 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7120 r_refdef.view.numfrustumplanes = 5;
7122 if (r_refdef.view.useclipplane)
7124 r_refdef.view.numfrustumplanes = 6;
7125 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7128 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7129 PlaneClassify(r_refdef.view.frustum + i);
7131 // LordHavoc: note to all quake engine coders, Quake had a special case
7132 // for 90 degrees which assumed a square view (wrong), so I removed it,
7133 // Quake2 has it disabled as well.
7135 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7136 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7137 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7138 //PlaneClassify(&frustum[0]);
7140 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7141 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7142 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7143 //PlaneClassify(&frustum[1]);
7145 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7146 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7147 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7148 //PlaneClassify(&frustum[2]);
7150 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7151 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7152 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7153 //PlaneClassify(&frustum[3]);
7156 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7157 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7158 //PlaneClassify(&frustum[4]);
7161 void R_View_Update(void)
7163 R_Main_ResizeViewCache();
7164 R_View_SetFrustum();
7165 R_View_WorldVisibility(r_refdef.view.useclipplane);
7166 R_View_UpdateEntityVisible();
7167 R_View_UpdateEntityLighting();
7170 void R_SetupView(qboolean allowwaterclippingplane)
7172 const float *customclipplane = NULL;
7174 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7176 // LordHavoc: couldn't figure out how to make this approach the
7177 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7178 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7179 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7180 dist = r_refdef.view.clipplane.dist;
7181 plane[0] = r_refdef.view.clipplane.normal[0];
7182 plane[1] = r_refdef.view.clipplane.normal[1];
7183 plane[2] = r_refdef.view.clipplane.normal[2];
7185 customclipplane = plane;
7188 if (!r_refdef.view.useperspective)
7189 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);
7190 else if (vid.stencil && r_useinfinitefarclip.integer)
7191 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);
7193 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);
7194 R_SetViewport(&r_refdef.view.viewport);
7197 void R_EntityMatrix(const matrix4x4_t *matrix)
7199 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7201 gl_modelmatrixchanged = false;
7202 gl_modelmatrix = *matrix;
7203 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7204 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7205 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7206 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7208 switch(vid.renderpath)
7210 case RENDERPATH_GL20:
7211 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7212 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7213 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7215 case RENDERPATH_CGGL:
7218 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7219 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7220 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7223 case RENDERPATH_GL13:
7224 case RENDERPATH_GL11:
7225 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7231 void R_ResetViewRendering2D(void)
7233 r_viewport_t viewport;
7236 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7237 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);
7238 R_SetViewport(&viewport);
7239 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7240 GL_Color(1, 1, 1, 1);
7241 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7242 GL_BlendFunc(GL_ONE, GL_ZERO);
7243 GL_AlphaTest(false);
7244 GL_ScissorTest(false);
7245 GL_DepthMask(false);
7246 GL_DepthRange(0, 1);
7247 GL_DepthTest(false);
7248 R_EntityMatrix(&identitymatrix);
7249 R_Mesh_ResetTextureState();
7250 GL_PolygonOffset(0, 0);
7251 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7252 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7253 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7254 qglStencilMask(~0);CHECKGLERROR
7255 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7256 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7257 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7260 void R_ResetViewRendering3D(void)
7265 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7266 GL_Color(1, 1, 1, 1);
7267 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7268 GL_BlendFunc(GL_ONE, GL_ZERO);
7269 GL_AlphaTest(false);
7270 GL_ScissorTest(true);
7272 GL_DepthRange(0, 1);
7274 R_EntityMatrix(&identitymatrix);
7275 R_Mesh_ResetTextureState();
7276 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7277 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7278 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7279 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7280 qglStencilMask(~0);CHECKGLERROR
7281 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7282 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7283 GL_CullFace(r_refdef.view.cullface_back);
7286 void R_RenderScene(void);
7287 void R_RenderWaterPlanes(void);
7289 static void R_Water_StartFrame(void)
7292 int waterwidth, waterheight, texturewidth, textureheight;
7293 r_waterstate_waterplane_t *p;
7295 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7298 switch(vid.renderpath)
7300 case RENDERPATH_GL20:
7301 case RENDERPATH_CGGL:
7303 case RENDERPATH_GL13:
7304 case RENDERPATH_GL11:
7308 // set waterwidth and waterheight to the water resolution that will be
7309 // used (often less than the screen resolution for faster rendering)
7310 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7311 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7313 // calculate desired texture sizes
7314 // can't use water if the card does not support the texture size
7315 if (!r_water.integer || r_showsurfaces.integer)
7316 texturewidth = textureheight = waterwidth = waterheight = 0;
7317 else if (vid.support.arb_texture_non_power_of_two)
7319 texturewidth = waterwidth;
7320 textureheight = waterheight;
7324 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
7325 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
7328 // allocate textures as needed
7329 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
7331 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7332 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7334 if (p->texture_refraction)
7335 R_FreeTexture(p->texture_refraction);
7336 p->texture_refraction = NULL;
7337 if (p->texture_reflection)
7338 R_FreeTexture(p->texture_reflection);
7339 p->texture_reflection = NULL;
7341 memset(&r_waterstate, 0, sizeof(r_waterstate));
7342 r_waterstate.texturewidth = texturewidth;
7343 r_waterstate.textureheight = textureheight;
7346 if (r_waterstate.texturewidth)
7348 r_waterstate.enabled = true;
7350 // when doing a reduced render (HDR) we want to use a smaller area
7351 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7352 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7354 // set up variables that will be used in shader setup
7355 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7356 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7357 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7358 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7361 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7362 r_waterstate.numwaterplanes = 0;
7365 void R_Water_AddWaterPlane(msurface_t *surface)
7367 int triangleindex, planeindex;
7373 r_waterstate_waterplane_t *p;
7374 texture_t *t = R_GetCurrentTexture(surface->texture);
7375 // just use the first triangle with a valid normal for any decisions
7376 VectorClear(normal);
7377 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7379 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7380 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7381 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7382 TriangleNormal(vert[0], vert[1], vert[2], normal);
7383 if (VectorLength2(normal) >= 0.001)
7387 VectorCopy(normal, plane.normal);
7388 VectorNormalize(plane.normal);
7389 plane.dist = DotProduct(vert[0], plane.normal);
7390 PlaneClassify(&plane);
7391 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7393 // skip backfaces (except if nocullface is set)
7394 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7396 VectorNegate(plane.normal, plane.normal);
7398 PlaneClassify(&plane);
7402 // find a matching plane if there is one
7403 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7404 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7406 if (planeindex >= r_waterstate.maxwaterplanes)
7407 return; // nothing we can do, out of planes
7409 // if this triangle does not fit any known plane rendered this frame, add one
7410 if (planeindex >= r_waterstate.numwaterplanes)
7412 // store the new plane
7413 r_waterstate.numwaterplanes++;
7415 // clear materialflags and pvs
7416 p->materialflags = 0;
7417 p->pvsvalid = false;
7419 // merge this surface's materialflags into the waterplane
7420 p->materialflags |= t->currentmaterialflags;
7421 // merge this surface's PVS into the waterplane
7422 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7423 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7424 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7426 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7431 static void R_Water_ProcessPlanes(void)
7433 r_refdef_view_t originalview;
7434 r_refdef_view_t myview;
7436 r_waterstate_waterplane_t *p;
7438 originalview = r_refdef.view;
7440 // make sure enough textures are allocated
7441 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7443 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7445 if (!p->texture_refraction)
7446 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);
7447 if (!p->texture_refraction)
7451 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7453 if (!p->texture_reflection)
7454 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);
7455 if (!p->texture_reflection)
7461 r_refdef.view = originalview;
7462 r_refdef.view.showdebug = false;
7463 r_refdef.view.width = r_waterstate.waterwidth;
7464 r_refdef.view.height = r_waterstate.waterheight;
7465 r_refdef.view.useclipplane = true;
7466 myview = r_refdef.view;
7467 r_waterstate.renderingscene = true;
7468 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7470 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7472 r_refdef.view = myview;
7473 // render reflected scene and copy into texture
7474 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7475 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7476 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7477 r_refdef.view.clipplane = p->plane;
7478 // reverse the cullface settings for this render
7479 r_refdef.view.cullface_front = GL_FRONT;
7480 r_refdef.view.cullface_back = GL_BACK;
7481 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7483 r_refdef.view.usecustompvs = true;
7485 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7487 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7490 R_ResetViewRendering3D();
7491 R_ClearScreen(r_refdef.fogenabled);
7495 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);
7498 // render the normal view scene and copy into texture
7499 // (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)
7500 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7502 r_waterstate.renderingrefraction = true;
7503 r_refdef.view = myview;
7504 r_refdef.view.clipplane = p->plane;
7505 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7506 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7507 PlaneClassify(&r_refdef.view.clipplane);
7509 R_ResetViewRendering3D();
7510 R_ClearScreen(r_refdef.fogenabled);
7514 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);
7515 r_waterstate.renderingrefraction = false;
7519 r_waterstate.renderingscene = false;
7520 r_refdef.view = originalview;
7521 R_ResetViewRendering3D();
7522 R_ClearScreen(r_refdef.fogenabled);
7526 r_refdef.view = originalview;
7527 r_waterstate.renderingscene = false;
7528 Cvar_SetValueQuick(&r_water, 0);
7529 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
7533 void R_Bloom_StartFrame(void)
7535 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7537 switch(vid.renderpath)
7539 case RENDERPATH_GL20:
7540 case RENDERPATH_CGGL:
7542 case RENDERPATH_GL13:
7543 case RENDERPATH_GL11:
7547 // set bloomwidth and bloomheight to the bloom resolution that will be
7548 // used (often less than the screen resolution for faster rendering)
7549 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7550 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7551 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7552 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7553 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7555 // calculate desired texture sizes
7556 if (vid.support.arb_texture_non_power_of_two)
7558 screentexturewidth = r_refdef.view.width;
7559 screentextureheight = r_refdef.view.height;
7560 bloomtexturewidth = r_bloomstate.bloomwidth;
7561 bloomtextureheight = r_bloomstate.bloomheight;
7565 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
7566 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
7567 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
7568 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
7571 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))
7573 Cvar_SetValueQuick(&r_hdr, 0);
7574 Cvar_SetValueQuick(&r_bloom, 0);
7575 Cvar_SetValueQuick(&r_motionblur, 0);
7576 Cvar_SetValueQuick(&r_damageblur, 0);
7579 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)))
7580 screentexturewidth = screentextureheight = 0;
7581 if (!r_hdr.integer && !r_bloom.integer)
7582 bloomtexturewidth = bloomtextureheight = 0;
7584 // allocate textures as needed
7585 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7587 if (r_bloomstate.texture_screen)
7588 R_FreeTexture(r_bloomstate.texture_screen);
7589 r_bloomstate.texture_screen = NULL;
7590 r_bloomstate.screentexturewidth = screentexturewidth;
7591 r_bloomstate.screentextureheight = screentextureheight;
7592 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7593 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7595 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7597 if (r_bloomstate.texture_bloom)
7598 R_FreeTexture(r_bloomstate.texture_bloom);
7599 r_bloomstate.texture_bloom = NULL;
7600 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7601 r_bloomstate.bloomtextureheight = bloomtextureheight;
7602 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7603 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7606 // when doing a reduced render (HDR) we want to use a smaller area
7607 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7608 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7609 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7610 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7611 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7613 // set up a texcoord array for the full resolution screen image
7614 // (we have to keep this around to copy back during final render)
7615 r_bloomstate.screentexcoord2f[0] = 0;
7616 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7617 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7618 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7619 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7620 r_bloomstate.screentexcoord2f[5] = 0;
7621 r_bloomstate.screentexcoord2f[6] = 0;
7622 r_bloomstate.screentexcoord2f[7] = 0;
7624 // set up a texcoord array for the reduced resolution bloom image
7625 // (which will be additive blended over the screen image)
7626 r_bloomstate.bloomtexcoord2f[0] = 0;
7627 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7628 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7629 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7630 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7631 r_bloomstate.bloomtexcoord2f[5] = 0;
7632 r_bloomstate.bloomtexcoord2f[6] = 0;
7633 r_bloomstate.bloomtexcoord2f[7] = 0;
7635 if (r_hdr.integer || r_bloom.integer)
7637 r_bloomstate.enabled = true;
7638 r_bloomstate.hdr = r_hdr.integer != 0;
7641 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);
7644 void R_Bloom_CopyBloomTexture(float colorscale)
7646 r_refdef.stats.bloom++;
7648 // scale down screen texture to the bloom texture size
7650 R_SetViewport(&r_bloomstate.viewport);
7651 GL_BlendFunc(GL_ONE, GL_ZERO);
7652 GL_Color(colorscale, colorscale, colorscale, 1);
7653 // TODO: optimize with multitexture or GLSL
7654 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7655 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7656 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7657 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7659 // we now have a bloom image in the framebuffer
7660 // copy it into the bloom image texture for later processing
7661 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);
7662 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7665 void R_Bloom_CopyHDRTexture(void)
7667 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);
7668 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7671 void R_Bloom_MakeTexture(void)
7674 float xoffset, yoffset, r, brighten;
7676 r_refdef.stats.bloom++;
7678 R_ResetViewRendering2D();
7679 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7680 R_Mesh_ColorPointer(NULL, 0, 0);
7682 // we have a bloom image in the framebuffer
7684 R_SetViewport(&r_bloomstate.viewport);
7686 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7689 r = bound(0, r_bloom_colorexponent.value / x, 1);
7690 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7691 GL_Color(r, r, r, 1);
7692 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7693 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7694 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7695 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7697 // copy the vertically blurred bloom view to a texture
7698 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);
7699 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7702 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7703 brighten = r_bloom_brighten.value;
7705 brighten *= r_hdr_range.value;
7706 brighten = sqrt(brighten);
7708 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7709 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7710 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7712 for (dir = 0;dir < 2;dir++)
7714 // blend on at multiple vertical offsets to achieve a vertical blur
7715 // TODO: do offset blends using GLSL
7716 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7717 GL_BlendFunc(GL_ONE, GL_ZERO);
7718 for (x = -range;x <= range;x++)
7720 if (!dir){xoffset = 0;yoffset = x;}
7721 else {xoffset = x;yoffset = 0;}
7722 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7723 yoffset /= (float)r_bloomstate.bloomtextureheight;
7724 // compute a texcoord array with the specified x and y offset
7725 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7726 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7727 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7728 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7729 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7730 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7731 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7732 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7733 // this r value looks like a 'dot' particle, fading sharply to
7734 // black at the edges
7735 // (probably not realistic but looks good enough)
7736 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7737 //r = brighten/(range*2+1);
7738 r = brighten / (range * 2 + 1);
7740 r *= (1 - x*x/(float)(range*range));
7741 GL_Color(r, r, r, 1);
7742 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7743 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7744 GL_BlendFunc(GL_ONE, GL_ONE);
7747 // copy the vertically blurred bloom view to a texture
7748 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);
7749 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7752 // apply subtract last
7753 // (just like it would be in a GLSL shader)
7754 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7756 GL_BlendFunc(GL_ONE, GL_ZERO);
7757 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7758 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7759 GL_Color(1, 1, 1, 1);
7760 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7761 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7763 GL_BlendFunc(GL_ONE, GL_ONE);
7764 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7765 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7766 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7767 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7768 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7769 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7770 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7772 // copy the darkened bloom view to a texture
7773 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);
7774 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7778 void R_HDR_RenderBloomTexture(void)
7780 int oldwidth, oldheight;
7781 float oldcolorscale;
7783 oldcolorscale = r_refdef.view.colorscale;
7784 oldwidth = r_refdef.view.width;
7785 oldheight = r_refdef.view.height;
7786 r_refdef.view.width = r_bloomstate.bloomwidth;
7787 r_refdef.view.height = r_bloomstate.bloomheight;
7789 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
7790 // TODO: add exposure compensation features
7791 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7793 r_refdef.view.showdebug = false;
7794 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7796 R_ResetViewRendering3D();
7798 R_ClearScreen(r_refdef.fogenabled);
7799 if (r_timereport_active)
7800 R_TimeReport("HDRclear");
7803 if (r_timereport_active)
7804 R_TimeReport("visibility");
7806 // only do secondary renders with HDR if r_hdr is 2 or higher
7807 r_waterstate.numwaterplanes = 0;
7808 if (r_waterstate.enabled && r_hdr.integer >= 2)
7809 R_RenderWaterPlanes();
7811 r_refdef.view.showdebug = true;
7813 r_waterstate.numwaterplanes = 0;
7815 R_ResetViewRendering2D();
7817 R_Bloom_CopyHDRTexture();
7818 R_Bloom_MakeTexture();
7820 // restore the view settings
7821 r_refdef.view.width = oldwidth;
7822 r_refdef.view.height = oldheight;
7823 r_refdef.view.colorscale = oldcolorscale;
7825 R_ResetViewRendering3D();
7827 R_ClearScreen(r_refdef.fogenabled);
7828 if (r_timereport_active)
7829 R_TimeReport("viewclear");
7832 static void R_BlendView(void)
7834 unsigned int permutation;
7835 float uservecs[4][4];
7837 switch (vid.renderpath)
7839 case RENDERPATH_GL20:
7840 case RENDERPATH_CGGL:
7842 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7843 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7844 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7845 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7846 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7848 if (r_bloomstate.texture_screen)
7850 // make sure the buffer is available
7851 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7853 R_ResetViewRendering2D();
7854 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7855 R_Mesh_ColorPointer(NULL, 0, 0);
7857 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7859 // declare variables
7861 static float avgspeed;
7863 speed = VectorLength(cl.movement_velocity);
7865 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7866 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7868 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7869 speed = bound(0, speed, 1);
7870 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7872 // calculate values into a standard alpha
7873 cl.motionbluralpha = 1 - exp(-
7875 (r_motionblur.value * speed / 80)
7877 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7880 max(0.0001, cl.time - cl.oldtime) // fps independent
7883 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7884 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7886 if (cl.motionbluralpha > 0)
7888 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7889 GL_Color(1, 1, 1, cl.motionbluralpha);
7890 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7891 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7892 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7893 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7897 // copy view into the screen texture
7898 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);
7899 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7901 else if (!r_bloomstate.texture_bloom)
7903 // we may still have to do view tint...
7904 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7906 // apply a color tint to the whole view
7907 R_ResetViewRendering2D();
7908 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7909 R_Mesh_ColorPointer(NULL, 0, 0);
7910 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7911 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7912 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7913 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7915 break; // no screen processing, no bloom, skip it
7918 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7920 // render simple bloom effect
7921 // copy the screen and shrink it and darken it for the bloom process
7922 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7923 // make the bloom texture
7924 R_Bloom_MakeTexture();
7927 #if _MSC_VER >= 1400
7928 #define sscanf sscanf_s
7930 memset(uservecs, 0, sizeof(uservecs));
7931 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7932 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7933 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7934 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7936 R_ResetViewRendering2D();
7937 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7938 R_Mesh_ColorPointer(NULL, 0, 0);
7939 GL_Color(1, 1, 1, 1);
7940 GL_BlendFunc(GL_ONE, GL_ZERO);
7941 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7942 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7944 switch(vid.renderpath)
7946 case RENDERPATH_GL20:
7947 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7948 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
7949 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
7950 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7951 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]);
7952 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7953 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]);
7954 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]);
7955 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]);
7956 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]);
7957 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7958 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7960 case RENDERPATH_CGGL:
7962 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7963 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
7964 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
7965 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
7966 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
7967 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7968 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
7969 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
7970 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
7971 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
7972 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
7973 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7979 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7980 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7982 case RENDERPATH_GL13:
7983 case RENDERPATH_GL11:
7984 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7986 // apply a color tint to the whole view
7987 R_ResetViewRendering2D();
7988 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7989 R_Mesh_ColorPointer(NULL, 0, 0);
7990 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7991 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7992 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7993 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7999 matrix4x4_t r_waterscrollmatrix;
8001 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8003 if (r_refdef.fog_density)
8005 r_refdef.fogcolor[0] = r_refdef.fog_red;
8006 r_refdef.fogcolor[1] = r_refdef.fog_green;
8007 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8009 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8010 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8011 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8012 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8016 VectorCopy(r_refdef.fogcolor, fogvec);
8017 // color.rgb *= ContrastBoost * SceneBrightness;
8018 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8019 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8020 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8021 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8026 void R_UpdateVariables(void)
8030 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8032 r_refdef.farclip = r_farclip_base.value;
8033 if (r_refdef.scene.worldmodel)
8034 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8035 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8037 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8038 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8039 r_refdef.polygonfactor = 0;
8040 r_refdef.polygonoffset = 0;
8041 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8042 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8044 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8045 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8046 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8047 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8048 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8049 if (r_showsurfaces.integer)
8051 r_refdef.scene.rtworld = false;
8052 r_refdef.scene.rtworldshadows = false;
8053 r_refdef.scene.rtdlight = false;
8054 r_refdef.scene.rtdlightshadows = false;
8055 r_refdef.lightmapintensity = 0;
8058 if (gamemode == GAME_NEHAHRA)
8060 if (gl_fogenable.integer)
8062 r_refdef.oldgl_fogenable = true;
8063 r_refdef.fog_density = gl_fogdensity.value;
8064 r_refdef.fog_red = gl_fogred.value;
8065 r_refdef.fog_green = gl_foggreen.value;
8066 r_refdef.fog_blue = gl_fogblue.value;
8067 r_refdef.fog_alpha = 1;
8068 r_refdef.fog_start = 0;
8069 r_refdef.fog_end = gl_skyclip.value;
8070 r_refdef.fog_height = 1<<30;
8071 r_refdef.fog_fadedepth = 128;
8073 else if (r_refdef.oldgl_fogenable)
8075 r_refdef.oldgl_fogenable = false;
8076 r_refdef.fog_density = 0;
8077 r_refdef.fog_red = 0;
8078 r_refdef.fog_green = 0;
8079 r_refdef.fog_blue = 0;
8080 r_refdef.fog_alpha = 0;
8081 r_refdef.fog_start = 0;
8082 r_refdef.fog_end = 0;
8083 r_refdef.fog_height = 1<<30;
8084 r_refdef.fog_fadedepth = 128;
8088 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8089 r_refdef.fog_start = max(0, r_refdef.fog_start);
8090 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8092 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8094 if (r_refdef.fog_density && r_drawfog.integer)
8096 r_refdef.fogenabled = true;
8097 // this is the point where the fog reaches 0.9986 alpha, which we
8098 // consider a good enough cutoff point for the texture
8099 // (0.9986 * 256 == 255.6)
8100 if (r_fog_exp2.integer)
8101 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8103 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8104 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8105 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8106 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8107 // fog color was already set
8108 // update the fog texture
8109 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)
8110 R_BuildFogTexture();
8113 r_refdef.fogenabled = false;
8115 switch(vid.renderpath)
8117 case RENDERPATH_GL20:
8118 case RENDERPATH_CGGL:
8119 if(v_glslgamma.integer && !vid_gammatables_trivial)
8121 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8123 // build GLSL gamma texture
8124 #define RAMPWIDTH 256
8125 unsigned short ramp[RAMPWIDTH * 3];
8126 unsigned char rampbgr[RAMPWIDTH][4];
8129 r_texture_gammaramps_serial = vid_gammatables_serial;
8131 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8132 for(i = 0; i < RAMPWIDTH; ++i)
8134 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8135 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8136 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8139 if (r_texture_gammaramps)
8141 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8145 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);
8151 // remove GLSL gamma texture
8154 case RENDERPATH_GL13:
8155 case RENDERPATH_GL11:
8160 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8161 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8167 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8168 if( scenetype != r_currentscenetype ) {
8169 // store the old scenetype
8170 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8171 r_currentscenetype = scenetype;
8172 // move in the new scene
8173 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8182 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8184 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8185 if( scenetype == r_currentscenetype ) {
8186 return &r_refdef.scene;
8188 return &r_scenes_store[ scenetype ];
8197 void R_RenderView(void)
8199 if (r_timereport_active)
8200 R_TimeReport("start");
8201 r_textureframe++; // used only by R_GetCurrentTexture
8202 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8204 if (!r_drawentities.integer)
8205 r_refdef.scene.numentities = 0;
8207 R_AnimCache_ClearCache();
8208 R_FrameData_NewFrame();
8210 if (r_refdef.view.isoverlay)
8212 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8213 GL_Clear( GL_DEPTH_BUFFER_BIT );
8214 R_TimeReport("depthclear");
8216 r_refdef.view.showdebug = false;
8218 r_waterstate.enabled = false;
8219 r_waterstate.numwaterplanes = 0;
8227 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8228 return; //Host_Error ("R_RenderView: NULL worldmodel");
8230 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8232 // break apart the view matrix into vectors for various purposes
8233 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8234 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8235 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8236 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8237 // make an inverted copy of the view matrix for tracking sprites
8238 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8240 R_Shadow_UpdateWorldLightSelection();
8242 R_Bloom_StartFrame();
8243 R_Water_StartFrame();
8246 if (r_timereport_active)
8247 R_TimeReport("viewsetup");
8249 R_ResetViewRendering3D();
8251 if (r_refdef.view.clear || r_refdef.fogenabled)
8253 R_ClearScreen(r_refdef.fogenabled);
8254 if (r_timereport_active)
8255 R_TimeReport("viewclear");
8257 r_refdef.view.clear = true;
8259 // this produces a bloom texture to be used in R_BlendView() later
8260 if (r_hdr.integer && r_bloomstate.bloomwidth)
8262 R_HDR_RenderBloomTexture();
8263 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8264 r_textureframe++; // used only by R_GetCurrentTexture
8267 r_refdef.view.showdebug = true;
8270 if (r_timereport_active)
8271 R_TimeReport("visibility");
8273 r_waterstate.numwaterplanes = 0;
8274 if (r_waterstate.enabled)
8275 R_RenderWaterPlanes();
8278 r_waterstate.numwaterplanes = 0;
8281 if (r_timereport_active)
8282 R_TimeReport("blendview");
8284 GL_Scissor(0, 0, vid.width, vid.height);
8285 GL_ScissorTest(false);
8289 void R_RenderWaterPlanes(void)
8291 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8293 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8294 if (r_timereport_active)
8295 R_TimeReport("waterworld");
8298 // don't let sound skip if going slow
8299 if (r_refdef.scene.extraupdate)
8302 R_DrawModelsAddWaterPlanes();
8303 if (r_timereport_active)
8304 R_TimeReport("watermodels");
8306 if (r_waterstate.numwaterplanes)
8308 R_Water_ProcessPlanes();
8309 if (r_timereport_active)
8310 R_TimeReport("waterscenes");
8314 extern void R_DrawLightningBeams (void);
8315 extern void VM_CL_AddPolygonsToMeshQueue (void);
8316 extern void R_DrawPortals (void);
8317 extern cvar_t cl_locs_show;
8318 static void R_DrawLocs(void);
8319 static void R_DrawEntityBBoxes(void);
8320 static void R_DrawModelDecals(void);
8321 extern void R_DrawModelShadows(void);
8322 extern void R_DrawModelShadowMaps(void);
8323 extern cvar_t cl_decals_newsystem;
8324 extern qboolean r_shadow_usingdeferredprepass;
8325 void R_RenderScene(void)
8327 qboolean shadowmapping = false;
8329 r_refdef.stats.renders++;
8333 // don't let sound skip if going slow
8334 if (r_refdef.scene.extraupdate)
8337 R_MeshQueue_BeginScene();
8341 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);
8343 if (cl.csqc_vidvars.drawworld)
8345 // don't let sound skip if going slow
8346 if (r_refdef.scene.extraupdate)
8349 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8351 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8352 if (r_timereport_active)
8353 R_TimeReport("worldsky");
8356 if (R_DrawBrushModelsSky() && r_timereport_active)
8357 R_TimeReport("bmodelsky");
8359 if (skyrendermasked && skyrenderlater)
8361 // we have to force off the water clipping plane while rendering sky
8365 if (r_timereport_active)
8366 R_TimeReport("sky");
8370 R_AnimCache_CacheVisibleEntities();
8371 if (r_timereport_active)
8372 R_TimeReport("animation");
8374 R_Shadow_PrepareLights();
8375 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8376 R_Shadow_PrepareModelShadows();
8377 if (r_timereport_active)
8378 R_TimeReport("preparelights");
8380 if (R_Shadow_ShadowMappingEnabled())
8381 shadowmapping = true;
8383 if (r_shadow_usingdeferredprepass)
8384 R_Shadow_DrawPrepass();
8386 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8388 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8389 if (r_timereport_active)
8390 R_TimeReport("worlddepth");
8392 if (r_depthfirst.integer >= 2)
8394 R_DrawModelsDepth();
8395 if (r_timereport_active)
8396 R_TimeReport("modeldepth");
8399 if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8401 R_DrawModelShadowMaps();
8402 R_ResetViewRendering3D();
8403 // don't let sound skip if going slow
8404 if (r_refdef.scene.extraupdate)
8408 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8410 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8411 if (r_timereport_active)
8412 R_TimeReport("world");
8415 // don't let sound skip if going slow
8416 if (r_refdef.scene.extraupdate)
8420 if (r_timereport_active)
8421 R_TimeReport("models");
8423 // don't let sound skip if going slow
8424 if (r_refdef.scene.extraupdate)
8427 if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8429 R_DrawModelShadows();
8430 R_ResetViewRendering3D();
8431 // don't let sound skip if going slow
8432 if (r_refdef.scene.extraupdate)
8436 if (!r_shadow_usingdeferredprepass)
8438 R_Shadow_DrawLights();
8439 if (r_timereport_active)
8440 R_TimeReport("rtlights");
8443 // don't let sound skip if going slow
8444 if (r_refdef.scene.extraupdate)
8447 if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8449 R_DrawModelShadows();
8450 R_ResetViewRendering3D();
8451 // don't let sound skip if going slow
8452 if (r_refdef.scene.extraupdate)
8456 if (cl.csqc_vidvars.drawworld)
8458 if (cl_decals_newsystem.integer)
8460 R_DrawModelDecals();
8461 if (r_timereport_active)
8462 R_TimeReport("modeldecals");
8467 if (r_timereport_active)
8468 R_TimeReport("decals");
8472 if (r_timereport_active)
8473 R_TimeReport("particles");
8476 if (r_timereport_active)
8477 R_TimeReport("explosions");
8479 R_DrawLightningBeams();
8480 if (r_timereport_active)
8481 R_TimeReport("lightning");
8484 VM_CL_AddPolygonsToMeshQueue();
8486 if (r_refdef.view.showdebug)
8488 if (cl_locs_show.integer)
8491 if (r_timereport_active)
8492 R_TimeReport("showlocs");
8495 if (r_drawportals.integer)
8498 if (r_timereport_active)
8499 R_TimeReport("portals");
8502 if (r_showbboxes.value > 0)
8504 R_DrawEntityBBoxes();
8505 if (r_timereport_active)
8506 R_TimeReport("bboxes");
8510 R_MeshQueue_RenderTransparent();
8511 if (r_timereport_active)
8512 R_TimeReport("drawtrans");
8514 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))
8516 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8517 if (r_timereport_active)
8518 R_TimeReport("worlddebug");
8519 R_DrawModelsDebug();
8520 if (r_timereport_active)
8521 R_TimeReport("modeldebug");
8524 if (cl.csqc_vidvars.drawworld)
8526 R_Shadow_DrawCoronas();
8527 if (r_timereport_active)
8528 R_TimeReport("coronas");
8531 // don't let sound skip if going slow
8532 if (r_refdef.scene.extraupdate)
8535 R_ResetViewRendering2D();
8538 static const unsigned short bboxelements[36] =
8548 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8551 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8553 RSurf_ActiveWorldEntity();
8555 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8556 GL_DepthMask(false);
8557 GL_DepthRange(0, 1);
8558 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8559 R_Mesh_ResetTextureState();
8561 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8562 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8563 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8564 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8565 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8566 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8567 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8568 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8569 R_FillColors(color4f, 8, cr, cg, cb, ca);
8570 if (r_refdef.fogenabled)
8572 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8574 f1 = RSurf_FogVertex(v);
8576 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8577 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8578 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8581 R_Mesh_VertexPointer(vertex3f, 0, 0);
8582 R_Mesh_ColorPointer(color4f, 0, 0);
8583 R_Mesh_ResetTextureState();
8584 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8585 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8588 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8592 prvm_edict_t *edict;
8593 prvm_prog_t *prog_save = prog;
8595 // this function draws bounding boxes of server entities
8599 GL_CullFace(GL_NONE);
8600 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8604 for (i = 0;i < numsurfaces;i++)
8606 edict = PRVM_EDICT_NUM(surfacelist[i]);
8607 switch ((int)edict->fields.server->solid)
8609 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
8610 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
8611 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
8612 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8613 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
8614 default: Vector4Set(color, 0, 0, 0, 0.50);break;
8616 color[3] *= r_showbboxes.value;
8617 color[3] = bound(0, color[3], 1);
8618 GL_DepthTest(!r_showdisabledepthtest.integer);
8619 GL_CullFace(r_refdef.view.cullface_front);
8620 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8626 static void R_DrawEntityBBoxes(void)
8629 prvm_edict_t *edict;
8631 prvm_prog_t *prog_save = prog;
8633 // this function draws bounding boxes of server entities
8639 for (i = 0;i < prog->num_edicts;i++)
8641 edict = PRVM_EDICT_NUM(i);
8642 if (edict->priv.server->free)
8644 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8645 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8647 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8649 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8650 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8656 static const int nomodelelement3i[24] =
8668 static const unsigned short nomodelelement3s[24] =
8680 static const float nomodelvertex3f[6*3] =
8690 static const float nomodelcolor4f[6*4] =
8692 0.0f, 0.0f, 0.5f, 1.0f,
8693 0.0f, 0.0f, 0.5f, 1.0f,
8694 0.0f, 0.5f, 0.0f, 1.0f,
8695 0.0f, 0.5f, 0.0f, 1.0f,
8696 0.5f, 0.0f, 0.0f, 1.0f,
8697 0.5f, 0.0f, 0.0f, 1.0f
8700 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8706 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);
8708 // this is only called once per entity so numsurfaces is always 1, and
8709 // surfacelist is always {0}, so this code does not handle batches
8711 if (rsurface.ent_flags & RENDER_ADDITIVE)
8713 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8714 GL_DepthMask(false);
8716 else if (rsurface.colormod[3] < 1)
8718 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8719 GL_DepthMask(false);
8723 GL_BlendFunc(GL_ONE, GL_ZERO);
8726 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8727 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8728 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8729 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8730 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8731 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8732 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8733 R_Mesh_ColorPointer(color4f, 0, 0);
8734 for (i = 0, c = color4f;i < 6;i++, c += 4)
8736 c[0] *= rsurface.colormod[0];
8737 c[1] *= rsurface.colormod[1];
8738 c[2] *= rsurface.colormod[2];
8739 c[3] *= rsurface.colormod[3];
8741 if (r_refdef.fogenabled)
8743 for (i = 0, c = color4f;i < 6;i++, c += 4)
8745 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8747 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8748 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8749 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8752 R_Mesh_ResetTextureState();
8753 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8756 void R_DrawNoModel(entity_render_t *ent)
8759 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8760 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8761 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8763 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8766 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8768 vec3_t right1, right2, diff, normal;
8770 VectorSubtract (org2, org1, normal);
8772 // calculate 'right' vector for start
8773 VectorSubtract (r_refdef.view.origin, org1, diff);
8774 CrossProduct (normal, diff, right1);
8775 VectorNormalize (right1);
8777 // calculate 'right' vector for end
8778 VectorSubtract (r_refdef.view.origin, org2, diff);
8779 CrossProduct (normal, diff, right2);
8780 VectorNormalize (right2);
8782 vert[ 0] = org1[0] + width * right1[0];
8783 vert[ 1] = org1[1] + width * right1[1];
8784 vert[ 2] = org1[2] + width * right1[2];
8785 vert[ 3] = org1[0] - width * right1[0];
8786 vert[ 4] = org1[1] - width * right1[1];
8787 vert[ 5] = org1[2] - width * right1[2];
8788 vert[ 6] = org2[0] - width * right2[0];
8789 vert[ 7] = org2[1] - width * right2[1];
8790 vert[ 8] = org2[2] - width * right2[2];
8791 vert[ 9] = org2[0] + width * right2[0];
8792 vert[10] = org2[1] + width * right2[1];
8793 vert[11] = org2[2] + width * right2[2];
8796 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)
8798 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8799 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8800 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8801 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8802 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8803 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8804 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8805 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8806 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8807 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8808 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8809 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8812 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8817 VectorSet(v, x, y, z);
8818 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8819 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8821 if (i == mesh->numvertices)
8823 if (mesh->numvertices < mesh->maxvertices)
8825 VectorCopy(v, vertex3f);
8826 mesh->numvertices++;
8828 return mesh->numvertices;
8834 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8838 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8839 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8840 e = mesh->element3i + mesh->numtriangles * 3;
8841 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8843 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8844 if (mesh->numtriangles < mesh->maxtriangles)
8849 mesh->numtriangles++;
8851 element[1] = element[2];
8855 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8859 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8860 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8861 e = mesh->element3i + mesh->numtriangles * 3;
8862 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8864 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8865 if (mesh->numtriangles < mesh->maxtriangles)
8870 mesh->numtriangles++;
8872 element[1] = element[2];
8876 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8877 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8879 int planenum, planenum2;
8882 mplane_t *plane, *plane2;
8884 double temppoints[2][256*3];
8885 // figure out how large a bounding box we need to properly compute this brush
8887 for (w = 0;w < numplanes;w++)
8888 maxdist = max(maxdist, fabs(planes[w].dist));
8889 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8890 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8891 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8895 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8896 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8898 if (planenum2 == planenum)
8900 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);
8903 if (tempnumpoints < 3)
8905 // generate elements forming a triangle fan for this polygon
8906 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8910 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)
8912 texturelayer_t *layer;
8913 layer = t->currentlayers + t->currentnumlayers++;
8915 layer->depthmask = depthmask;
8916 layer->blendfunc1 = blendfunc1;
8917 layer->blendfunc2 = blendfunc2;
8918 layer->texture = texture;
8919 layer->texmatrix = *matrix;
8920 layer->color[0] = r;
8921 layer->color[1] = g;
8922 layer->color[2] = b;
8923 layer->color[3] = a;
8926 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8929 index = parms[2] + r_refdef.scene.time * parms[3];
8930 index -= floor(index);
8934 case Q3WAVEFUNC_NONE:
8935 case Q3WAVEFUNC_NOISE:
8936 case Q3WAVEFUNC_COUNT:
8939 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8940 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8941 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8942 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8943 case Q3WAVEFUNC_TRIANGLE:
8945 f = index - floor(index);
8956 return (float)(parms[0] + parms[1] * f);
8959 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8964 matrix4x4_t matrix, temp;
8965 switch(tcmod->tcmod)
8969 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8970 matrix = r_waterscrollmatrix;
8972 matrix = identitymatrix;
8974 case Q3TCMOD_ENTITYTRANSLATE:
8975 // this is used in Q3 to allow the gamecode to control texcoord
8976 // scrolling on the entity, which is not supported in darkplaces yet.
8977 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8979 case Q3TCMOD_ROTATE:
8980 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8981 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8982 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8985 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8987 case Q3TCMOD_SCROLL:
8988 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8990 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8991 w = (int) tcmod->parms[0];
8992 h = (int) tcmod->parms[1];
8993 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8995 idx = (int) floor(f * w * h);
8996 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8998 case Q3TCMOD_STRETCH:
8999 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9000 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9002 case Q3TCMOD_TRANSFORM:
9003 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
9004 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
9005 VectorSet(tcmat + 6, 0 , 0 , 1);
9006 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
9007 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9009 case Q3TCMOD_TURBULENT:
9010 // this is handled in the RSurf_PrepareVertices function
9011 matrix = identitymatrix;
9015 Matrix4x4_Concat(texmatrix, &matrix, &temp);
9018 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9020 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9021 char name[MAX_QPATH];
9022 skinframe_t *skinframe;
9023 unsigned char pixels[296*194];
9024 strlcpy(cache->name, skinname, sizeof(cache->name));
9025 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9026 if (developer_loading.integer)
9027 Con_Printf("loading %s\n", name);
9028 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9029 if (!skinframe || !skinframe->base)
9032 fs_offset_t filesize;
9034 f = FS_LoadFile(name, tempmempool, true, &filesize);
9037 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9038 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9042 cache->skinframe = skinframe;
9045 texture_t *R_GetCurrentTexture(texture_t *t)
9048 const entity_render_t *ent = rsurface.entity;
9049 dp_model_t *model = ent->model;
9050 q3shaderinfo_layer_tcmod_t *tcmod;
9052 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9053 return t->currentframe;
9054 t->update_lastrenderframe = r_textureframe;
9055 t->update_lastrenderentity = (void *)ent;
9057 // switch to an alternate material if this is a q1bsp animated material
9059 texture_t *texture = t;
9060 int s = rsurface.ent_skinnum;
9061 if ((unsigned int)s >= (unsigned int)model->numskins)
9063 if (model->skinscenes)
9065 if (model->skinscenes[s].framecount > 1)
9066 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9068 s = model->skinscenes[s].firstframe;
9071 t = t + s * model->num_surfaces;
9074 // use an alternate animation if the entity's frame is not 0,
9075 // and only if the texture has an alternate animation
9076 if (rsurface.ent_alttextures && t->anim_total[1])
9077 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9079 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9081 texture->currentframe = t;
9084 // update currentskinframe to be a qw skin or animation frame
9085 if (rsurface.ent_qwskin >= 0)
9087 i = rsurface.ent_qwskin;
9088 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9090 r_qwskincache_size = cl.maxclients;
9092 Mem_Free(r_qwskincache);
9093 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9095 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9096 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9097 t->currentskinframe = r_qwskincache[i].skinframe;
9098 if (t->currentskinframe == NULL)
9099 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9101 else if (t->numskinframes >= 2)
9102 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9103 if (t->backgroundnumskinframes >= 2)
9104 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9106 t->currentmaterialflags = t->basematerialflags;
9107 t->currentalpha = rsurface.colormod[3];
9108 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9109 t->currentalpha *= r_wateralpha.value;
9110 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9111 t->currentalpha *= t->r_water_wateralpha;
9112 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9113 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
9114 if (!(rsurface.ent_flags & RENDER_LIGHT))
9115 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9116 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9118 // pick a model lighting mode
9119 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9120 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9122 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9124 if (rsurface.ent_flags & RENDER_ADDITIVE)
9125 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9126 else if (t->currentalpha < 1)
9127 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9128 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9129 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9130 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9131 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9132 if (t->backgroundnumskinframes)
9133 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9134 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9136 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
9137 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9140 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
9141 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9142 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9144 // there is no tcmod
9145 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9147 t->currenttexmatrix = r_waterscrollmatrix;
9148 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9150 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9152 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9153 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9156 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9157 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9158 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9159 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9161 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9162 if (t->currentskinframe->qpixels)
9163 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9164 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9165 if (!t->basetexture)
9166 t->basetexture = r_texture_notexture;
9167 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9168 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9169 t->nmaptexture = t->currentskinframe->nmap;
9170 if (!t->nmaptexture)
9171 t->nmaptexture = r_texture_blanknormalmap;
9172 t->glosstexture = r_texture_black;
9173 t->glowtexture = t->currentskinframe->glow;
9174 t->fogtexture = t->currentskinframe->fog;
9175 t->reflectmasktexture = t->currentskinframe->reflect;
9176 if (t->backgroundnumskinframes)
9178 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9179 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9180 t->backgroundglosstexture = r_texture_black;
9181 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9182 if (!t->backgroundnmaptexture)
9183 t->backgroundnmaptexture = r_texture_blanknormalmap;
9187 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9188 t->backgroundnmaptexture = r_texture_blanknormalmap;
9189 t->backgroundglosstexture = r_texture_black;
9190 t->backgroundglowtexture = NULL;
9192 t->specularpower = r_shadow_glossexponent.value;
9193 // TODO: store reference values for these in the texture?
9194 t->specularscale = 0;
9195 if (r_shadow_gloss.integer > 0)
9197 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9199 if (r_shadow_glossintensity.value > 0)
9201 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9202 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9203 t->specularscale = r_shadow_glossintensity.value;
9206 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9208 t->glosstexture = r_texture_white;
9209 t->backgroundglosstexture = r_texture_white;
9210 t->specularscale = r_shadow_gloss2intensity.value;
9211 t->specularpower = r_shadow_gloss2exponent.value;
9214 t->specularscale *= t->specularscalemod;
9215 t->specularpower *= t->specularpowermod;
9217 // lightmaps mode looks bad with dlights using actual texturing, so turn
9218 // off the colormap and glossmap, but leave the normalmap on as it still
9219 // accurately represents the shading involved
9220 if (gl_lightmaps.integer)
9222 t->basetexture = r_texture_grey128;
9223 t->pantstexture = r_texture_black;
9224 t->shirttexture = r_texture_black;
9225 t->nmaptexture = r_texture_blanknormalmap;
9226 t->glosstexture = r_texture_black;
9227 t->glowtexture = NULL;
9228 t->fogtexture = NULL;
9229 t->reflectmasktexture = NULL;
9230 t->backgroundbasetexture = NULL;
9231 t->backgroundnmaptexture = r_texture_blanknormalmap;
9232 t->backgroundglosstexture = r_texture_black;
9233 t->backgroundglowtexture = NULL;
9234 t->specularscale = 0;
9235 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9238 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9239 VectorClear(t->dlightcolor);
9240 t->currentnumlayers = 0;
9241 if (t->currentmaterialflags & MATERIALFLAG_WALL)
9243 int blendfunc1, blendfunc2;
9245 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9247 blendfunc1 = GL_SRC_ALPHA;
9248 blendfunc2 = GL_ONE;
9250 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9252 blendfunc1 = GL_SRC_ALPHA;
9253 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9255 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9257 blendfunc1 = t->customblendfunc[0];
9258 blendfunc2 = t->customblendfunc[1];
9262 blendfunc1 = GL_ONE;
9263 blendfunc2 = GL_ZERO;
9265 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9266 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9268 // fullbright is not affected by r_refdef.lightmapintensity
9269 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]);
9270 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9271 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]);
9272 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9273 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]);
9277 vec3_t ambientcolor;
9279 // set the color tint used for lights affecting this surface
9280 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9282 // q3bsp has no lightmap updates, so the lightstylevalue that
9283 // would normally be baked into the lightmap must be
9284 // applied to the color
9285 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9286 if (model->type == mod_brushq3)
9287 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9288 colorscale *= r_refdef.lightmapintensity;
9289 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9290 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9291 // basic lit geometry
9292 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]);
9293 // add pants/shirt if needed
9294 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9295 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]);
9296 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9297 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]);
9298 // now add ambient passes if needed
9299 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9301 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]);
9302 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9303 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]);
9304 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9305 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]);
9308 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9309 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]);
9310 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9312 // if this is opaque use alpha blend which will darken the earlier
9315 // if this is an alpha blended material, all the earlier passes
9316 // were darkened by fog already, so we only need to add the fog
9317 // color ontop through the fog mask texture
9319 // if this is an additive blended material, all the earlier passes
9320 // were darkened by fog already, and we should not add fog color
9321 // (because the background was not darkened, there is no fog color
9322 // that was lost behind it).
9323 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]);
9327 return t->currentframe;
9330 rsurfacestate_t rsurface;
9332 void R_Mesh_ResizeArrays(int newvertices)
9335 if (rsurface.array_size >= newvertices)
9337 if (rsurface.array_modelvertex3f)
9338 Mem_Free(rsurface.array_modelvertex3f);
9339 rsurface.array_size = (newvertices + 1023) & ~1023;
9340 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9341 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
9342 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
9343 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
9344 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
9345 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
9346 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9347 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9348 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
9349 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
9350 rsurface.array_color4f = base + rsurface.array_size * 27;
9351 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9354 void RSurf_ActiveWorldEntity(void)
9356 dp_model_t *model = r_refdef.scene.worldmodel;
9357 //if (rsurface.entity == r_refdef.scene.worldentity)
9359 rsurface.entity = r_refdef.scene.worldentity;
9360 rsurface.skeleton = NULL;
9361 rsurface.ent_skinnum = 0;
9362 rsurface.ent_qwskin = -1;
9363 rsurface.ent_shadertime = 0;
9364 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9365 if (rsurface.array_size < model->surfmesh.num_vertices)
9366 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9367 rsurface.matrix = identitymatrix;
9368 rsurface.inversematrix = identitymatrix;
9369 rsurface.matrixscale = 1;
9370 rsurface.inversematrixscale = 1;
9371 R_EntityMatrix(&identitymatrix);
9372 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9373 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9374 rsurface.fograngerecip = r_refdef.fograngerecip;
9375 rsurface.fogheightfade = r_refdef.fogheightfade;
9376 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9377 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9378 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9379 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9380 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9381 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9382 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9383 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9384 rsurface.colormod[3] = 1;
9385 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);
9386 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9387 rsurface.frameblend[0].lerp = 1;
9388 rsurface.ent_alttextures = false;
9389 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9390 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9391 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9392 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9393 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9394 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9395 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9396 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9397 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9398 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9399 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9400 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9401 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9402 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9403 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9404 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9405 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9406 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9407 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9408 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9409 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9410 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9411 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9412 rsurface.modelelement3i = model->surfmesh.data_element3i;
9413 rsurface.modelelement3s = model->surfmesh.data_element3s;
9414 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9415 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9416 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9417 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9418 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9419 rsurface.modelsurfaces = model->data_surfaces;
9420 rsurface.generatedvertex = false;
9421 rsurface.vertex3f = rsurface.modelvertex3f;
9422 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9423 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9424 rsurface.svector3f = rsurface.modelsvector3f;
9425 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9426 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9427 rsurface.tvector3f = rsurface.modeltvector3f;
9428 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9429 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9430 rsurface.normal3f = rsurface.modelnormal3f;
9431 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9432 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9433 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9436 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9438 dp_model_t *model = ent->model;
9439 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9441 rsurface.entity = (entity_render_t *)ent;
9442 rsurface.skeleton = ent->skeleton;
9443 rsurface.ent_skinnum = ent->skinnum;
9444 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;
9445 rsurface.ent_shadertime = ent->shadertime;
9446 rsurface.ent_flags = ent->flags;
9447 if (rsurface.array_size < model->surfmesh.num_vertices)
9448 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9449 rsurface.matrix = ent->matrix;
9450 rsurface.inversematrix = ent->inversematrix;
9451 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9452 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9453 R_EntityMatrix(&rsurface.matrix);
9454 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9455 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9456 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9457 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9458 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9459 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9460 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9461 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9462 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9463 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9464 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9465 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9466 rsurface.colormod[3] = ent->alpha;
9467 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9468 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9469 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9470 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9471 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9472 if (ent->model->brush.submodel && !prepass)
9474 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9475 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9477 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9479 if (ent->animcache_vertex3f && !r_framedata_failed)
9481 rsurface.modelvertex3f = ent->animcache_vertex3f;
9482 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9483 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9484 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9486 else if (wanttangents)
9488 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9489 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9490 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9491 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9492 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9494 else if (wantnormals)
9496 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9497 rsurface.modelsvector3f = NULL;
9498 rsurface.modeltvector3f = NULL;
9499 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9500 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9504 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9505 rsurface.modelsvector3f = NULL;
9506 rsurface.modeltvector3f = NULL;
9507 rsurface.modelnormal3f = NULL;
9508 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9510 rsurface.modelvertex3f_bufferobject = 0;
9511 rsurface.modelvertex3f_bufferoffset = 0;
9512 rsurface.modelsvector3f_bufferobject = 0;
9513 rsurface.modelsvector3f_bufferoffset = 0;
9514 rsurface.modeltvector3f_bufferobject = 0;
9515 rsurface.modeltvector3f_bufferoffset = 0;
9516 rsurface.modelnormal3f_bufferobject = 0;
9517 rsurface.modelnormal3f_bufferoffset = 0;
9518 rsurface.generatedvertex = true;
9522 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9523 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9524 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9525 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9526 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9527 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9528 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9529 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9530 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9531 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9532 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9533 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9534 rsurface.generatedvertex = false;
9536 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9537 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9538 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9539 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9540 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9541 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9542 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9543 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9544 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9545 rsurface.modelelement3i = model->surfmesh.data_element3i;
9546 rsurface.modelelement3s = model->surfmesh.data_element3s;
9547 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9548 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9549 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9550 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9551 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9552 rsurface.modelsurfaces = model->data_surfaces;
9553 rsurface.vertex3f = rsurface.modelvertex3f;
9554 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9555 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9556 rsurface.svector3f = rsurface.modelsvector3f;
9557 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9558 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9559 rsurface.tvector3f = rsurface.modeltvector3f;
9560 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9561 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9562 rsurface.normal3f = rsurface.modelnormal3f;
9563 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9564 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9565 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9568 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)
9570 rsurface.entity = r_refdef.scene.worldentity;
9571 rsurface.skeleton = NULL;
9572 rsurface.ent_skinnum = 0;
9573 rsurface.ent_qwskin = -1;
9574 rsurface.ent_shadertime = shadertime;
9575 rsurface.ent_flags = entflags;
9576 rsurface.modelnum_vertices = numvertices;
9577 rsurface.modelnum_triangles = numtriangles;
9578 if (rsurface.array_size < rsurface.modelnum_vertices)
9579 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9580 rsurface.matrix = *matrix;
9581 rsurface.inversematrix = *inversematrix;
9582 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9583 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9584 R_EntityMatrix(&rsurface.matrix);
9585 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9586 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9587 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9588 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9589 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9590 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9591 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9592 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9593 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9594 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9595 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9596 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9597 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);
9598 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9599 rsurface.frameblend[0].lerp = 1;
9600 rsurface.ent_alttextures = false;
9601 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9602 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9605 rsurface.modelvertex3f = vertex3f;
9606 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9607 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9608 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9610 else if (wantnormals)
9612 rsurface.modelvertex3f = vertex3f;
9613 rsurface.modelsvector3f = NULL;
9614 rsurface.modeltvector3f = NULL;
9615 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9619 rsurface.modelvertex3f = vertex3f;
9620 rsurface.modelsvector3f = NULL;
9621 rsurface.modeltvector3f = NULL;
9622 rsurface.modelnormal3f = NULL;
9624 rsurface.modelvertex3f_bufferobject = 0;
9625 rsurface.modelvertex3f_bufferoffset = 0;
9626 rsurface.modelsvector3f_bufferobject = 0;
9627 rsurface.modelsvector3f_bufferoffset = 0;
9628 rsurface.modeltvector3f_bufferobject = 0;
9629 rsurface.modeltvector3f_bufferoffset = 0;
9630 rsurface.modelnormal3f_bufferobject = 0;
9631 rsurface.modelnormal3f_bufferoffset = 0;
9632 rsurface.generatedvertex = true;
9633 rsurface.modellightmapcolor4f = color4f;
9634 rsurface.modellightmapcolor4f_bufferobject = 0;
9635 rsurface.modellightmapcolor4f_bufferoffset = 0;
9636 rsurface.modeltexcoordtexture2f = texcoord2f;
9637 rsurface.modeltexcoordtexture2f_bufferobject = 0;
9638 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9639 rsurface.modeltexcoordlightmap2f = NULL;
9640 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9641 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9642 rsurface.modelelement3i = element3i;
9643 rsurface.modelelement3s = element3s;
9644 rsurface.modelelement3i_bufferobject = 0;
9645 rsurface.modelelement3s_bufferobject = 0;
9646 rsurface.modellightmapoffsets = NULL;
9647 rsurface.modelsurfaces = NULL;
9648 rsurface.vertex3f = rsurface.modelvertex3f;
9649 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9650 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9651 rsurface.svector3f = rsurface.modelsvector3f;
9652 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9653 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9654 rsurface.tvector3f = rsurface.modeltvector3f;
9655 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9656 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9657 rsurface.normal3f = rsurface.modelnormal3f;
9658 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9659 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9660 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9662 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9664 if ((wantnormals || wanttangents) && !normal3f)
9665 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9666 if (wanttangents && !svector3f)
9667 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);
9671 float RSurf_FogPoint(const float *v)
9673 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9674 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9675 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9676 float FogHeightFade = r_refdef.fogheightfade;
9678 unsigned int fogmasktableindex;
9679 if (r_refdef.fogplaneviewabove)
9680 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9682 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9683 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9684 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9687 float RSurf_FogVertex(const float *v)
9689 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9690 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9691 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9692 float FogHeightFade = rsurface.fogheightfade;
9694 unsigned int fogmasktableindex;
9695 if (r_refdef.fogplaneviewabove)
9696 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9698 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9699 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9700 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9703 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9704 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9707 int texturesurfaceindex;
9712 const float *v1, *in_tc;
9714 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9716 q3shaderinfo_deform_t *deform;
9717 // 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
9718 if (rsurface.generatedvertex)
9720 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9721 generatenormals = true;
9722 for (i = 0;i < Q3MAXDEFORMS;i++)
9724 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9726 generatetangents = true;
9727 generatenormals = true;
9729 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9730 generatenormals = true;
9732 if (generatenormals && !rsurface.modelnormal3f)
9734 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9735 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9736 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9737 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9739 if (generatetangents && !rsurface.modelsvector3f)
9741 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9742 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9743 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9744 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9745 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9746 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9747 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);
9750 rsurface.vertex3f = rsurface.modelvertex3f;
9751 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9752 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9753 rsurface.svector3f = rsurface.modelsvector3f;
9754 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9755 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9756 rsurface.tvector3f = rsurface.modeltvector3f;
9757 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9758 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9759 rsurface.normal3f = rsurface.modelnormal3f;
9760 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9761 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9762 // if vertices are deformed (sprite flares and things in maps, possibly
9763 // water waves, bulges and other deformations), generate them into
9764 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9765 // (may be static model data or generated data for an animated model, or
9766 // the previous deform pass)
9767 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9769 switch (deform->deform)
9772 case Q3DEFORM_PROJECTIONSHADOW:
9773 case Q3DEFORM_TEXT0:
9774 case Q3DEFORM_TEXT1:
9775 case Q3DEFORM_TEXT2:
9776 case Q3DEFORM_TEXT3:
9777 case Q3DEFORM_TEXT4:
9778 case Q3DEFORM_TEXT5:
9779 case Q3DEFORM_TEXT6:
9780 case Q3DEFORM_TEXT7:
9783 case Q3DEFORM_AUTOSPRITE:
9784 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9785 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9786 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9787 VectorNormalize(newforward);
9788 VectorNormalize(newright);
9789 VectorNormalize(newup);
9790 // make deformed versions of only the model vertices used by the specified surfaces
9791 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9793 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9794 // a single autosprite surface can contain multiple sprites...
9795 for (j = 0;j < surface->num_vertices - 3;j += 4)
9797 VectorClear(center);
9798 for (i = 0;i < 4;i++)
9799 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9800 VectorScale(center, 0.25f, center);
9801 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9802 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9803 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9804 for (i = 0;i < 4;i++)
9806 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9807 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9810 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);
9811 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);
9813 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9814 rsurface.vertex3f_bufferobject = 0;
9815 rsurface.vertex3f_bufferoffset = 0;
9816 rsurface.svector3f = rsurface.array_deformedsvector3f;
9817 rsurface.svector3f_bufferobject = 0;
9818 rsurface.svector3f_bufferoffset = 0;
9819 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9820 rsurface.tvector3f_bufferobject = 0;
9821 rsurface.tvector3f_bufferoffset = 0;
9822 rsurface.normal3f = rsurface.array_deformednormal3f;
9823 rsurface.normal3f_bufferobject = 0;
9824 rsurface.normal3f_bufferoffset = 0;
9826 case Q3DEFORM_AUTOSPRITE2:
9827 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9828 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9829 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9830 VectorNormalize(newforward);
9831 VectorNormalize(newright);
9832 VectorNormalize(newup);
9833 // make deformed versions of only the model vertices used by the specified surfaces
9834 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9836 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9837 const float *v1, *v2;
9847 memset(shortest, 0, sizeof(shortest));
9848 // a single autosprite surface can contain multiple sprites...
9849 for (j = 0;j < surface->num_vertices - 3;j += 4)
9851 VectorClear(center);
9852 for (i = 0;i < 4;i++)
9853 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9854 VectorScale(center, 0.25f, center);
9855 // find the two shortest edges, then use them to define the
9856 // axis vectors for rotating around the central axis
9857 for (i = 0;i < 6;i++)
9859 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9860 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9862 Debug_PolygonBegin(NULL, 0);
9863 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9864 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);
9865 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9868 l = VectorDistance2(v1, v2);
9869 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9871 l += (1.0f / 1024.0f);
9872 if (shortest[0].length2 > l || i == 0)
9874 shortest[1] = shortest[0];
9875 shortest[0].length2 = l;
9876 shortest[0].v1 = v1;
9877 shortest[0].v2 = v2;
9879 else if (shortest[1].length2 > l || i == 1)
9881 shortest[1].length2 = l;
9882 shortest[1].v1 = v1;
9883 shortest[1].v2 = v2;
9886 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9887 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9889 Debug_PolygonBegin(NULL, 0);
9890 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9891 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);
9892 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9895 // this calculates the right vector from the shortest edge
9896 // and the up vector from the edge midpoints
9897 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9898 VectorNormalize(right);
9899 VectorSubtract(end, start, up);
9900 VectorNormalize(up);
9901 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9902 VectorSubtract(rsurface.localvieworigin, center, forward);
9903 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9904 VectorNegate(forward, forward);
9905 VectorReflect(forward, 0, up, forward);
9906 VectorNormalize(forward);
9907 CrossProduct(up, forward, newright);
9908 VectorNormalize(newright);
9910 Debug_PolygonBegin(NULL, 0);
9911 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);
9912 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9913 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9917 Debug_PolygonBegin(NULL, 0);
9918 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9919 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9920 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9923 // rotate the quad around the up axis vector, this is made
9924 // especially easy by the fact we know the quad is flat,
9925 // so we only have to subtract the center position and
9926 // measure distance along the right vector, and then
9927 // multiply that by the newright vector and add back the
9929 // we also need to subtract the old position to undo the
9930 // displacement from the center, which we do with a
9931 // DotProduct, the subtraction/addition of center is also
9932 // optimized into DotProducts here
9933 l = DotProduct(right, center);
9934 for (i = 0;i < 4;i++)
9936 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9937 f = DotProduct(right, v1) - l;
9938 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9941 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);
9942 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);
9944 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9945 rsurface.vertex3f_bufferobject = 0;
9946 rsurface.vertex3f_bufferoffset = 0;
9947 rsurface.svector3f = rsurface.array_deformedsvector3f;
9948 rsurface.svector3f_bufferobject = 0;
9949 rsurface.svector3f_bufferoffset = 0;
9950 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9951 rsurface.tvector3f_bufferobject = 0;
9952 rsurface.tvector3f_bufferoffset = 0;
9953 rsurface.normal3f = rsurface.array_deformednormal3f;
9954 rsurface.normal3f_bufferobject = 0;
9955 rsurface.normal3f_bufferoffset = 0;
9957 case Q3DEFORM_NORMAL:
9958 // deform the normals to make reflections wavey
9959 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9961 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9962 for (j = 0;j < surface->num_vertices;j++)
9965 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9966 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9967 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9968 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9969 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9970 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9971 VectorNormalize(normal);
9973 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);
9975 rsurface.svector3f = rsurface.array_deformedsvector3f;
9976 rsurface.svector3f_bufferobject = 0;
9977 rsurface.svector3f_bufferoffset = 0;
9978 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9979 rsurface.tvector3f_bufferobject = 0;
9980 rsurface.tvector3f_bufferoffset = 0;
9981 rsurface.normal3f = rsurface.array_deformednormal3f;
9982 rsurface.normal3f_bufferobject = 0;
9983 rsurface.normal3f_bufferoffset = 0;
9986 // deform vertex array to make wavey water and flags and such
9987 waveparms[0] = deform->waveparms[0];
9988 waveparms[1] = deform->waveparms[1];
9989 waveparms[2] = deform->waveparms[2];
9990 waveparms[3] = deform->waveparms[3];
9991 // this is how a divisor of vertex influence on deformation
9992 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9993 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9994 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9996 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9997 for (j = 0;j < surface->num_vertices;j++)
9999 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
10000 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
10001 // if the wavefunc depends on time, evaluate it per-vertex
10004 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
10005 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10007 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
10010 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10011 rsurface.vertex3f_bufferobject = 0;
10012 rsurface.vertex3f_bufferoffset = 0;
10014 case Q3DEFORM_BULGE:
10015 // deform vertex array to make the surface have moving bulges
10016 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10018 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10019 for (j = 0;j < surface->num_vertices;j++)
10021 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
10022 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10025 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10026 rsurface.vertex3f_bufferobject = 0;
10027 rsurface.vertex3f_bufferoffset = 0;
10029 case Q3DEFORM_MOVE:
10030 // deform vertex array
10031 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10032 VectorScale(deform->parms, scale, waveparms);
10033 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10035 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10036 for (j = 0;j < surface->num_vertices;j++)
10037 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10039 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10040 rsurface.vertex3f_bufferobject = 0;
10041 rsurface.vertex3f_bufferoffset = 0;
10045 // generate texcoords based on the chosen texcoord source
10046 switch(rsurface.texture->tcgen.tcgen)
10049 case Q3TCGEN_TEXTURE:
10050 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10051 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
10052 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
10054 case Q3TCGEN_LIGHTMAP:
10055 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
10056 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10057 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10059 case Q3TCGEN_VECTOR:
10060 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10062 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10063 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)
10065 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10066 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10069 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10070 rsurface.texcoordtexture2f_bufferobject = 0;
10071 rsurface.texcoordtexture2f_bufferoffset = 0;
10073 case Q3TCGEN_ENVIRONMENT:
10074 // make environment reflections using a spheremap
10075 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10077 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10078 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10079 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10080 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10081 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10083 // identical to Q3A's method, but executed in worldspace so
10084 // carried models can be shiny too
10086 float viewer[3], d, reflected[3], worldreflected[3];
10088 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10089 // VectorNormalize(viewer);
10091 d = DotProduct(normal, viewer);
10093 reflected[0] = normal[0]*2*d - viewer[0];
10094 reflected[1] = normal[1]*2*d - viewer[1];
10095 reflected[2] = normal[2]*2*d - viewer[2];
10096 // note: this is proportinal to viewer, so we can normalize later
10098 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10099 VectorNormalize(worldreflected);
10101 // note: this sphere map only uses world x and z!
10102 // so positive and negative y will LOOK THE SAME.
10103 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10104 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10107 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10108 rsurface.texcoordtexture2f_bufferobject = 0;
10109 rsurface.texcoordtexture2f_bufferoffset = 0;
10112 // the only tcmod that needs software vertex processing is turbulent, so
10113 // check for it here and apply the changes if needed
10114 // and we only support that as the first one
10115 // (handling a mixture of turbulent and other tcmods would be problematic
10116 // without punting it entirely to a software path)
10117 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10119 amplitude = rsurface.texture->tcmods[0].parms[1];
10120 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10121 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10123 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10124 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)
10126 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10127 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10130 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10131 rsurface.texcoordtexture2f_bufferobject = 0;
10132 rsurface.texcoordtexture2f_bufferoffset = 0;
10134 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10135 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10136 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10137 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10140 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10143 const msurface_t *surface = texturesurfacelist[0];
10144 const msurface_t *surface2;
10149 // TODO: lock all array ranges before render, rather than on each surface
10150 if (texturenumsurfaces == 1)
10151 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);
10152 else if (r_batchmode.integer == 2)
10154 #define MAXBATCHTRIANGLES 4096
10155 int batchtriangles = 0;
10156 static int batchelements[MAXBATCHTRIANGLES*3];
10157 for (i = 0;i < texturenumsurfaces;i = j)
10159 surface = texturesurfacelist[i];
10161 if (surface->num_triangles > MAXBATCHTRIANGLES)
10163 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);
10166 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10167 batchtriangles = surface->num_triangles;
10168 firstvertex = surface->num_firstvertex;
10169 endvertex = surface->num_firstvertex + surface->num_vertices;
10170 for (;j < texturenumsurfaces;j++)
10172 surface2 = texturesurfacelist[j];
10173 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10175 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10176 batchtriangles += surface2->num_triangles;
10177 firstvertex = min(firstvertex, surface2->num_firstvertex);
10178 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10180 surface2 = texturesurfacelist[j-1];
10181 numvertices = endvertex - firstvertex;
10182 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10185 else if (r_batchmode.integer == 1)
10187 for (i = 0;i < texturenumsurfaces;i = j)
10189 surface = texturesurfacelist[i];
10190 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10191 if (texturesurfacelist[j] != surface2)
10193 surface2 = texturesurfacelist[j-1];
10194 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10195 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10196 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10201 for (i = 0;i < texturenumsurfaces;i++)
10203 surface = texturesurfacelist[i];
10204 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);
10209 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10211 switch(vid.renderpath)
10213 case RENDERPATH_CGGL:
10215 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10216 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10219 case RENDERPATH_GL20:
10220 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10221 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10223 case RENDERPATH_GL13:
10224 case RENDERPATH_GL11:
10225 R_Mesh_TexBind(0, surface->lightmaptexture);
10230 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10232 // pick the closest matching water plane and bind textures
10233 int planeindex, vertexindex;
10237 r_waterstate_waterplane_t *p, *bestp;
10240 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10243 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10245 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10246 d += fabs(PlaneDiff(vert, &p->plane));
10248 if (bestd > d || !bestp)
10254 switch(vid.renderpath)
10256 case RENDERPATH_CGGL:
10258 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10259 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10262 case RENDERPATH_GL20:
10263 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10264 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10266 case RENDERPATH_GL13:
10267 case RENDERPATH_GL11:
10272 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10275 const msurface_t *surface;
10276 if (r_waterstate.renderingscene)
10278 for (i = 0;i < texturenumsurfaces;i++)
10280 surface = texturesurfacelist[i];
10281 RSurf_BindLightmapForSurface(surface);
10282 RSurf_BindReflectionForSurface(surface);
10283 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);
10287 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10291 const msurface_t *surface = texturesurfacelist[0];
10292 const msurface_t *surface2;
10297 if (texturenumsurfaces == 1)
10299 RSurf_BindLightmapForSurface(surface);
10300 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);
10302 else if (r_batchmode.integer == 2)
10304 #define MAXBATCHTRIANGLES 4096
10305 int batchtriangles = 0;
10306 static int batchelements[MAXBATCHTRIANGLES*3];
10307 for (i = 0;i < texturenumsurfaces;i = j)
10309 surface = texturesurfacelist[i];
10310 RSurf_BindLightmapForSurface(surface);
10312 if (surface->num_triangles > MAXBATCHTRIANGLES)
10314 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);
10317 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10318 batchtriangles = surface->num_triangles;
10319 firstvertex = surface->num_firstvertex;
10320 endvertex = surface->num_firstvertex + surface->num_vertices;
10321 for (;j < texturenumsurfaces;j++)
10323 surface2 = texturesurfacelist[j];
10324 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10326 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10327 batchtriangles += surface2->num_triangles;
10328 firstvertex = min(firstvertex, surface2->num_firstvertex);
10329 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10331 surface2 = texturesurfacelist[j-1];
10332 numvertices = endvertex - firstvertex;
10333 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10336 else if (r_batchmode.integer == 1)
10339 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10340 for (i = 0;i < texturenumsurfaces;i = j)
10342 surface = texturesurfacelist[i];
10343 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10344 if (texturesurfacelist[j] != surface2)
10346 Con_Printf(" %i", j - i);
10349 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10351 for (i = 0;i < texturenumsurfaces;i = j)
10353 surface = texturesurfacelist[i];
10354 RSurf_BindLightmapForSurface(surface);
10355 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10356 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10359 Con_Printf(" %i", j - i);
10361 surface2 = texturesurfacelist[j-1];
10362 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10363 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10364 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10372 for (i = 0;i < texturenumsurfaces;i++)
10374 surface = texturesurfacelist[i];
10375 RSurf_BindLightmapForSurface(surface);
10376 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);
10381 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10384 int texturesurfaceindex;
10385 if (r_showsurfaces.integer == 2)
10387 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10389 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10390 for (j = 0;j < surface->num_triangles;j++)
10392 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10393 GL_Color(f, f, f, 1);
10394 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10400 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10402 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10403 int k = (int)(((size_t)surface) / sizeof(msurface_t));
10404 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);
10405 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);
10410 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10412 int texturesurfaceindex;
10416 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10418 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10419 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)
10427 rsurface.lightmapcolor4f = rsurface.array_color4f;
10428 rsurface.lightmapcolor4f_bufferobject = 0;
10429 rsurface.lightmapcolor4f_bufferoffset = 0;
10432 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10434 int texturesurfaceindex;
10440 if (rsurface.lightmapcolor4f)
10442 // generate color arrays for the surfaces in this list
10443 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10445 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10446 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)
10448 f = RSurf_FogVertex(v);
10458 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10460 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10461 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)
10463 f = RSurf_FogVertex(v);
10471 rsurface.lightmapcolor4f = rsurface.array_color4f;
10472 rsurface.lightmapcolor4f_bufferobject = 0;
10473 rsurface.lightmapcolor4f_bufferoffset = 0;
10476 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10478 int texturesurfaceindex;
10484 if (!rsurface.lightmapcolor4f)
10486 // generate color arrays for the surfaces in this list
10487 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10489 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10490 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)
10492 f = RSurf_FogVertex(v);
10493 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10494 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10495 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10499 rsurface.lightmapcolor4f = rsurface.array_color4f;
10500 rsurface.lightmapcolor4f_bufferobject = 0;
10501 rsurface.lightmapcolor4f_bufferoffset = 0;
10504 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10506 int texturesurfaceindex;
10510 if (!rsurface.lightmapcolor4f)
10512 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10514 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10515 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)
10523 rsurface.lightmapcolor4f = rsurface.array_color4f;
10524 rsurface.lightmapcolor4f_bufferobject = 0;
10525 rsurface.lightmapcolor4f_bufferoffset = 0;
10528 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10530 int texturesurfaceindex;
10534 if (!rsurface.lightmapcolor4f)
10536 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10538 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10539 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)
10541 c2[0] = c[0] + r_refdef.scene.ambient;
10542 c2[1] = c[1] + r_refdef.scene.ambient;
10543 c2[2] = c[2] + r_refdef.scene.ambient;
10547 rsurface.lightmapcolor4f = rsurface.array_color4f;
10548 rsurface.lightmapcolor4f_bufferobject = 0;
10549 rsurface.lightmapcolor4f_bufferoffset = 0;
10552 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10555 rsurface.lightmapcolor4f = NULL;
10556 rsurface.lightmapcolor4f_bufferobject = 0;
10557 rsurface.lightmapcolor4f_bufferoffset = 0;
10558 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10559 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10560 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10561 GL_Color(r, g, b, a);
10562 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10565 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10567 // TODO: optimize applyfog && applycolor case
10568 // just apply fog if necessary, and tint the fog color array if necessary
10569 rsurface.lightmapcolor4f = NULL;
10570 rsurface.lightmapcolor4f_bufferobject = 0;
10571 rsurface.lightmapcolor4f_bufferoffset = 0;
10572 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10573 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10574 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10575 GL_Color(r, g, b, a);
10576 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10579 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10581 int texturesurfaceindex;
10585 if (texturesurfacelist[0]->lightmapinfo)
10587 // generate color arrays for the surfaces in this list
10588 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10590 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10591 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10593 if (surface->lightmapinfo->samples)
10595 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10596 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10597 VectorScale(lm, scale, c);
10598 if (surface->lightmapinfo->styles[1] != 255)
10600 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10602 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10603 VectorMA(c, scale, lm, c);
10604 if (surface->lightmapinfo->styles[2] != 255)
10607 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10608 VectorMA(c, scale, lm, c);
10609 if (surface->lightmapinfo->styles[3] != 255)
10612 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10613 VectorMA(c, scale, lm, c);
10623 rsurface.lightmapcolor4f = rsurface.array_color4f;
10624 rsurface.lightmapcolor4f_bufferobject = 0;
10625 rsurface.lightmapcolor4f_bufferoffset = 0;
10629 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10630 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10631 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10633 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10634 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10635 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10636 GL_Color(r, g, b, a);
10637 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10640 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10642 int texturesurfaceindex;
10649 vec3_t ambientcolor;
10650 vec3_t diffusecolor;
10654 VectorCopy(rsurface.modellight_lightdir, lightdir);
10655 f = 0.5f * r_refdef.lightmapintensity;
10656 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10657 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10658 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10659 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10660 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10661 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10663 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10665 // generate color arrays for the surfaces in this list
10666 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10668 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10669 int numverts = surface->num_vertices;
10670 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10671 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10672 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10673 // q3-style directional shading
10674 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10676 if ((f = DotProduct(n, lightdir)) > 0)
10677 VectorMA(ambientcolor, f, diffusecolor, c);
10679 VectorCopy(ambientcolor, c);
10687 rsurface.lightmapcolor4f = rsurface.array_color4f;
10688 rsurface.lightmapcolor4f_bufferobject = 0;
10689 rsurface.lightmapcolor4f_bufferoffset = 0;
10690 *applycolor = false;
10694 *r = ambientcolor[0];
10695 *g = ambientcolor[1];
10696 *b = ambientcolor[2];
10697 rsurface.lightmapcolor4f = NULL;
10698 rsurface.lightmapcolor4f_bufferobject = 0;
10699 rsurface.lightmapcolor4f_bufferoffset = 0;
10703 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10705 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10706 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10707 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10708 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10709 GL_Color(r, g, b, a);
10710 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10713 void RSurf_SetupDepthAndCulling(void)
10715 // submodels are biased to avoid z-fighting with world surfaces that they
10716 // may be exactly overlapping (avoids z-fighting artifacts on certain
10717 // doors and things in Quake maps)
10718 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10719 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10720 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10721 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10724 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10726 // transparent sky would be ridiculous
10727 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10729 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10730 skyrenderlater = true;
10731 RSurf_SetupDepthAndCulling();
10732 GL_DepthMask(true);
10733 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10734 // skymasking on them, and Quake3 never did sky masking (unlike
10735 // software Quake and software Quake2), so disable the sky masking
10736 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10737 // and skymasking also looks very bad when noclipping outside the
10738 // level, so don't use it then either.
10739 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10741 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10742 R_Mesh_ColorPointer(NULL, 0, 0);
10743 R_Mesh_ResetTextureState();
10744 if (skyrendermasked)
10746 R_SetupShader_DepthOrShadow();
10747 // depth-only (masking)
10748 GL_ColorMask(0,0,0,0);
10749 // just to make sure that braindead drivers don't draw
10750 // anything despite that colormask...
10751 GL_BlendFunc(GL_ZERO, GL_ONE);
10755 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10757 GL_BlendFunc(GL_ONE, GL_ZERO);
10759 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10760 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10761 if (skyrendermasked)
10762 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10764 R_Mesh_ResetTextureState();
10765 GL_Color(1, 1, 1, 1);
10768 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10769 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10770 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10772 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10774 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10777 // render screenspace normalmap to texture
10778 GL_DepthMask(true);
10779 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10780 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10782 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10784 // render water or distortion background, then blend surface on top
10785 GL_DepthMask(true);
10786 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10787 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10788 GL_DepthMask(false);
10789 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10790 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10791 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10793 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10797 // render surface normally
10798 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10799 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10800 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10801 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10802 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10803 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10805 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10809 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10811 // OpenGL 1.3 path - anything not completely ancient
10812 int texturesurfaceindex;
10813 qboolean applycolor;
10816 const texturelayer_t *layer;
10817 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10819 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10822 int layertexrgbscale;
10823 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10825 if (layerindex == 0)
10826 GL_AlphaTest(true);
10829 GL_AlphaTest(false);
10830 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10833 GL_DepthMask(layer->depthmask && writedepth);
10834 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10835 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10837 layertexrgbscale = 4;
10838 VectorScale(layer->color, 0.25f, layercolor);
10840 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10842 layertexrgbscale = 2;
10843 VectorScale(layer->color, 0.5f, layercolor);
10847 layertexrgbscale = 1;
10848 VectorScale(layer->color, 1.0f, layercolor);
10850 layercolor[3] = layer->color[3];
10851 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10852 R_Mesh_ColorPointer(NULL, 0, 0);
10853 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10854 switch (layer->type)
10856 case TEXTURELAYERTYPE_LITTEXTURE:
10857 // single-pass lightmapped texture with 2x rgbscale
10858 R_Mesh_TexBind(0, r_texture_white);
10859 R_Mesh_TexMatrix(0, NULL);
10860 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10861 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10862 R_Mesh_TexBind(1, layer->texture);
10863 R_Mesh_TexMatrix(1, &layer->texmatrix);
10864 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10865 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10866 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10867 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10868 else if (rsurface.uselightmaptexture)
10869 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10871 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10873 case TEXTURELAYERTYPE_TEXTURE:
10874 // singletexture unlit texture with transparency support
10875 R_Mesh_TexBind(0, layer->texture);
10876 R_Mesh_TexMatrix(0, &layer->texmatrix);
10877 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10878 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10879 R_Mesh_TexBind(1, 0);
10880 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10881 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10883 case TEXTURELAYERTYPE_FOG:
10884 // singletexture fogging
10885 if (layer->texture)
10887 R_Mesh_TexBind(0, layer->texture);
10888 R_Mesh_TexMatrix(0, &layer->texmatrix);
10889 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10890 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10894 R_Mesh_TexBind(0, 0);
10895 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10897 R_Mesh_TexBind(1, 0);
10898 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10899 // generate a color array for the fog pass
10900 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10901 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10907 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10908 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)
10910 f = 1 - RSurf_FogVertex(v);
10911 c[0] = layercolor[0];
10912 c[1] = layercolor[1];
10913 c[2] = layercolor[2];
10914 c[3] = f * layercolor[3];
10917 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10920 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10924 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10926 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10927 GL_AlphaTest(false);
10931 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10933 // OpenGL 1.1 - crusty old voodoo path
10934 int texturesurfaceindex;
10937 const texturelayer_t *layer;
10938 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10940 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10942 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10944 if (layerindex == 0)
10945 GL_AlphaTest(true);
10948 GL_AlphaTest(false);
10949 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10952 GL_DepthMask(layer->depthmask && writedepth);
10953 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10954 R_Mesh_ColorPointer(NULL, 0, 0);
10955 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10956 switch (layer->type)
10958 case TEXTURELAYERTYPE_LITTEXTURE:
10959 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10961 // two-pass lit texture with 2x rgbscale
10962 // first the lightmap pass
10963 R_Mesh_TexBind(0, r_texture_white);
10964 R_Mesh_TexMatrix(0, NULL);
10965 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10966 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10967 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10968 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10969 else if (rsurface.uselightmaptexture)
10970 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10972 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10973 // then apply the texture to it
10974 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10975 R_Mesh_TexBind(0, layer->texture);
10976 R_Mesh_TexMatrix(0, &layer->texmatrix);
10977 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10978 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10979 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);
10983 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10984 R_Mesh_TexBind(0, layer->texture);
10985 R_Mesh_TexMatrix(0, &layer->texmatrix);
10986 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10987 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10988 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10989 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);
10991 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);
10994 case TEXTURELAYERTYPE_TEXTURE:
10995 // singletexture unlit texture with transparency support
10996 R_Mesh_TexBind(0, layer->texture);
10997 R_Mesh_TexMatrix(0, &layer->texmatrix);
10998 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10999 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11000 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);
11002 case TEXTURELAYERTYPE_FOG:
11003 // singletexture fogging
11004 if (layer->texture)
11006 R_Mesh_TexBind(0, layer->texture);
11007 R_Mesh_TexMatrix(0, &layer->texmatrix);
11008 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11009 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11013 R_Mesh_TexBind(0, 0);
11014 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11016 // generate a color array for the fog pass
11017 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11018 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11024 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11025 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)
11027 f = 1 - RSurf_FogVertex(v);
11028 c[0] = layer->color[0];
11029 c[1] = layer->color[1];
11030 c[2] = layer->color[2];
11031 c[3] = f * layer->color[3];
11034 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11037 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11041 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11043 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11044 GL_AlphaTest(false);
11048 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11052 GL_AlphaTest(false);
11053 R_Mesh_ColorPointer(NULL, 0, 0);
11054 R_Mesh_ResetTextureState();
11055 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11057 if(rsurface.texture && rsurface.texture->currentskinframe)
11059 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11060 c[3] *= rsurface.texture->currentalpha;
11070 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11072 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11073 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11074 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11077 // brighten it up (as texture value 127 means "unlit")
11078 c[0] *= 2 * r_refdef.view.colorscale;
11079 c[1] *= 2 * r_refdef.view.colorscale;
11080 c[2] *= 2 * r_refdef.view.colorscale;
11082 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11083 c[3] *= r_wateralpha.value;
11085 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11087 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11088 GL_DepthMask(false);
11090 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11092 GL_BlendFunc(GL_ONE, GL_ONE);
11093 GL_DepthMask(false);
11095 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11097 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11098 GL_DepthMask(false);
11100 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11102 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11103 GL_DepthMask(false);
11107 GL_BlendFunc(GL_ONE, GL_ZERO);
11108 GL_DepthMask(writedepth);
11111 rsurface.lightmapcolor4f = NULL;
11113 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11115 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11117 rsurface.lightmapcolor4f = NULL;
11118 rsurface.lightmapcolor4f_bufferobject = 0;
11119 rsurface.lightmapcolor4f_bufferoffset = 0;
11121 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11123 qboolean applycolor = true;
11126 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11128 r_refdef.lightmapintensity = 1;
11129 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11130 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11134 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11136 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11137 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11138 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11141 if(!rsurface.lightmapcolor4f)
11142 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11144 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11145 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11146 if(r_refdef.fogenabled)
11147 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11149 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11150 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11153 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11156 RSurf_SetupDepthAndCulling();
11157 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11159 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11162 switch (vid.renderpath)
11164 case RENDERPATH_GL20:
11165 case RENDERPATH_CGGL:
11166 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11168 case RENDERPATH_GL13:
11169 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11171 case RENDERPATH_GL11:
11172 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11178 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11181 RSurf_SetupDepthAndCulling();
11182 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11184 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11187 switch (vid.renderpath)
11189 case RENDERPATH_GL20:
11190 case RENDERPATH_CGGL:
11191 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11193 case RENDERPATH_GL13:
11194 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11196 case RENDERPATH_GL11:
11197 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11203 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11206 int texturenumsurfaces, endsurface;
11207 texture_t *texture;
11208 const msurface_t *surface;
11209 const msurface_t *texturesurfacelist[256];
11211 // if the model is static it doesn't matter what value we give for
11212 // wantnormals and wanttangents, so this logic uses only rules applicable
11213 // to a model, knowing that they are meaningless otherwise
11214 if (ent == r_refdef.scene.worldentity)
11215 RSurf_ActiveWorldEntity();
11216 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11217 RSurf_ActiveModelEntity(ent, false, false, false);
11220 switch (vid.renderpath)
11222 case RENDERPATH_GL20:
11223 case RENDERPATH_CGGL:
11224 RSurf_ActiveModelEntity(ent, true, true, false);
11226 case RENDERPATH_GL13:
11227 case RENDERPATH_GL11:
11228 RSurf_ActiveModelEntity(ent, true, false, false);
11233 if (r_transparentdepthmasking.integer)
11235 qboolean setup = false;
11236 for (i = 0;i < numsurfaces;i = j)
11239 surface = rsurface.modelsurfaces + surfacelist[i];
11240 texture = surface->texture;
11241 rsurface.texture = R_GetCurrentTexture(texture);
11242 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11243 // scan ahead until we find a different texture
11244 endsurface = min(i + 1024, numsurfaces);
11245 texturenumsurfaces = 0;
11246 texturesurfacelist[texturenumsurfaces++] = surface;
11247 for (;j < endsurface;j++)
11249 surface = rsurface.modelsurfaces + surfacelist[j];
11250 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11252 texturesurfacelist[texturenumsurfaces++] = surface;
11254 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11256 // render the range of surfaces as depth
11260 GL_ColorMask(0,0,0,0);
11262 GL_DepthTest(true);
11263 GL_BlendFunc(GL_ONE, GL_ZERO);
11264 GL_DepthMask(true);
11265 GL_AlphaTest(false);
11266 R_Mesh_ColorPointer(NULL, 0, 0);
11267 R_Mesh_ResetTextureState();
11268 R_SetupShader_DepthOrShadow();
11270 RSurf_SetupDepthAndCulling();
11271 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11272 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11275 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11278 for (i = 0;i < numsurfaces;i = j)
11281 surface = rsurface.modelsurfaces + surfacelist[i];
11282 texture = surface->texture;
11283 rsurface.texture = R_GetCurrentTexture(texture);
11284 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11285 // scan ahead until we find a different texture
11286 endsurface = min(i + 1024, numsurfaces);
11287 texturenumsurfaces = 0;
11288 texturesurfacelist[texturenumsurfaces++] = surface;
11289 for (;j < endsurface;j++)
11291 surface = rsurface.modelsurfaces + surfacelist[j];
11292 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11294 texturesurfacelist[texturenumsurfaces++] = surface;
11296 // render the range of surfaces
11297 if (ent == r_refdef.scene.worldentity)
11298 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11300 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11302 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11303 GL_AlphaTest(false);
11306 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11308 // transparent surfaces get pushed off into the transparent queue
11309 int surfacelistindex;
11310 const msurface_t *surface;
11311 vec3_t tempcenter, center;
11312 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11314 surface = texturesurfacelist[surfacelistindex];
11315 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11316 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11317 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11318 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11319 if (queueentity->transparent_offset) // transparent offset
11321 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11322 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11323 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11325 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11329 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11331 const entity_render_t *queueentity = r_refdef.scene.worldentity;
11335 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11337 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11339 RSurf_SetupDepthAndCulling();
11340 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11341 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11345 if (!rsurface.texture->currentnumlayers)
11347 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11348 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11350 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11352 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11354 RSurf_SetupDepthAndCulling();
11355 GL_AlphaTest(false);
11356 R_Mesh_ColorPointer(NULL, 0, 0);
11357 R_Mesh_ResetTextureState();
11358 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11359 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11360 GL_DepthMask(true);
11361 GL_BlendFunc(GL_ONE, GL_ZERO);
11362 GL_Color(0, 0, 0, 1);
11363 GL_DepthTest(writedepth);
11364 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11366 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11368 RSurf_SetupDepthAndCulling();
11369 GL_AlphaTest(false);
11370 R_Mesh_ColorPointer(NULL, 0, 0);
11371 R_Mesh_ResetTextureState();
11372 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11373 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11374 GL_DepthMask(true);
11375 GL_BlendFunc(GL_ONE, GL_ZERO);
11376 GL_DepthTest(true);
11377 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11379 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11380 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11381 else if (!rsurface.texture->currentnumlayers)
11383 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11385 // in the deferred case, transparent surfaces were queued during prepass
11386 if (!r_shadow_usingdeferredprepass)
11387 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11391 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11392 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11397 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11400 texture_t *texture;
11401 // break the surface list down into batches by texture and use of lightmapping
11402 for (i = 0;i < numsurfaces;i = j)
11405 // texture is the base texture pointer, rsurface.texture is the
11406 // current frame/skin the texture is directing us to use (for example
11407 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11408 // use skin 1 instead)
11409 texture = surfacelist[i]->texture;
11410 rsurface.texture = R_GetCurrentTexture(texture);
11411 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11412 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11414 // if this texture is not the kind we want, skip ahead to the next one
11415 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11419 // simply scan ahead until we find a different texture or lightmap state
11420 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11422 // render the range of surfaces
11423 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11427 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11432 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11434 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11436 RSurf_SetupDepthAndCulling();
11437 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11438 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11442 if (!rsurface.texture->currentnumlayers)
11444 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11445 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11447 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11449 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11451 RSurf_SetupDepthAndCulling();
11452 GL_AlphaTest(false);
11453 R_Mesh_ColorPointer(NULL, 0, 0);
11454 R_Mesh_ResetTextureState();
11455 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11456 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11457 GL_DepthMask(true);
11458 GL_BlendFunc(GL_ONE, GL_ZERO);
11459 GL_Color(0, 0, 0, 1);
11460 GL_DepthTest(writedepth);
11461 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11463 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11465 RSurf_SetupDepthAndCulling();
11466 GL_AlphaTest(false);
11467 R_Mesh_ColorPointer(NULL, 0, 0);
11468 R_Mesh_ResetTextureState();
11469 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11470 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11471 GL_DepthMask(true);
11472 GL_BlendFunc(GL_ONE, GL_ZERO);
11473 GL_DepthTest(true);
11474 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11476 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11477 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11478 else if (!rsurface.texture->currentnumlayers)
11480 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11482 // in the deferred case, transparent surfaces were queued during prepass
11483 if (!r_shadow_usingdeferredprepass)
11484 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11488 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11489 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11494 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11497 texture_t *texture;
11498 // break the surface list down into batches by texture and use of lightmapping
11499 for (i = 0;i < numsurfaces;i = j)
11502 // texture is the base texture pointer, rsurface.texture is the
11503 // current frame/skin the texture is directing us to use (for example
11504 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11505 // use skin 1 instead)
11506 texture = surfacelist[i]->texture;
11507 rsurface.texture = R_GetCurrentTexture(texture);
11508 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11509 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11511 // if this texture is not the kind we want, skip ahead to the next one
11512 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11516 // simply scan ahead until we find a different texture or lightmap state
11517 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11519 // render the range of surfaces
11520 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11524 float locboxvertex3f[6*4*3] =
11526 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11527 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11528 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11529 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11530 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11531 1,0,0, 0,0,0, 0,1,0, 1,1,0
11534 unsigned short locboxelements[6*2*3] =
11539 12,13,14, 12,14,15,
11540 16,17,18, 16,18,19,
11544 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11547 cl_locnode_t *loc = (cl_locnode_t *)ent;
11549 float vertex3f[6*4*3];
11551 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11552 GL_DepthMask(false);
11553 GL_DepthRange(0, 1);
11554 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11555 GL_DepthTest(true);
11556 GL_CullFace(GL_NONE);
11557 R_EntityMatrix(&identitymatrix);
11559 R_Mesh_VertexPointer(vertex3f, 0, 0);
11560 R_Mesh_ColorPointer(NULL, 0, 0);
11561 R_Mesh_ResetTextureState();
11562 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11564 i = surfacelist[0];
11565 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11566 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11567 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11568 surfacelist[0] < 0 ? 0.5f : 0.125f);
11570 if (VectorCompare(loc->mins, loc->maxs))
11572 VectorSet(size, 2, 2, 2);
11573 VectorMA(loc->mins, -0.5f, size, mins);
11577 VectorCopy(loc->mins, mins);
11578 VectorSubtract(loc->maxs, loc->mins, size);
11581 for (i = 0;i < 6*4*3;)
11582 for (j = 0;j < 3;j++, i++)
11583 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11585 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11588 void R_DrawLocs(void)
11591 cl_locnode_t *loc, *nearestloc;
11593 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11594 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11596 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11597 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11601 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11603 if (decalsystem->decals)
11604 Mem_Free(decalsystem->decals);
11605 memset(decalsystem, 0, sizeof(*decalsystem));
11608 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)
11611 tridecal_t *decals;
11614 // expand or initialize the system
11615 if (decalsystem->maxdecals <= decalsystem->numdecals)
11617 decalsystem_t old = *decalsystem;
11618 qboolean useshortelements;
11619 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11620 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11621 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)));
11622 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11623 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11624 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11625 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11626 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11627 if (decalsystem->numdecals)
11628 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11630 Mem_Free(old.decals);
11631 for (i = 0;i < decalsystem->maxdecals*3;i++)
11632 decalsystem->element3i[i] = i;
11633 if (useshortelements)
11634 for (i = 0;i < decalsystem->maxdecals*3;i++)
11635 decalsystem->element3s[i] = i;
11638 // grab a decal and search for another free slot for the next one
11639 decals = decalsystem->decals;
11640 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11641 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11643 decalsystem->freedecal = i;
11644 if (decalsystem->numdecals <= i)
11645 decalsystem->numdecals = i + 1;
11647 // initialize the decal
11649 decal->triangleindex = triangleindex;
11650 decal->surfaceindex = surfaceindex;
11651 decal->decalsequence = decalsequence;
11652 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11653 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11654 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11655 decal->color4ub[0][3] = 255;
11656 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11657 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11658 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11659 decal->color4ub[1][3] = 255;
11660 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11661 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11662 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11663 decal->color4ub[2][3] = 255;
11664 decal->vertex3f[0][0] = v0[0];
11665 decal->vertex3f[0][1] = v0[1];
11666 decal->vertex3f[0][2] = v0[2];
11667 decal->vertex3f[1][0] = v1[0];
11668 decal->vertex3f[1][1] = v1[1];
11669 decal->vertex3f[1][2] = v1[2];
11670 decal->vertex3f[2][0] = v2[0];
11671 decal->vertex3f[2][1] = v2[1];
11672 decal->vertex3f[2][2] = v2[2];
11673 decal->texcoord2f[0][0] = t0[0];
11674 decal->texcoord2f[0][1] = t0[1];
11675 decal->texcoord2f[1][0] = t1[0];
11676 decal->texcoord2f[1][1] = t1[1];
11677 decal->texcoord2f[2][0] = t2[0];
11678 decal->texcoord2f[2][1] = t2[1];
11681 extern cvar_t cl_decals_bias;
11682 extern cvar_t cl_decals_models;
11683 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11684 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)
11686 matrix4x4_t projection;
11687 decalsystem_t *decalsystem;
11690 const float *vertex3f;
11691 const msurface_t *surface;
11692 const msurface_t *surfaces;
11693 const int *surfacelist;
11694 const texture_t *texture;
11696 int numsurfacelist;
11697 int surfacelistindex;
11704 float localorigin[3];
11705 float localnormal[3];
11706 float localmins[3];
11707 float localmaxs[3];
11713 float planes[6][4];
11715 float points[2][9][3];
11719 decalsystem = &ent->decalsystem;
11720 model = ent->model;
11721 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11723 R_DecalSystem_Reset(&ent->decalsystem);
11727 if (!model->brush.data_nodes && !cl_decals_models.integer)
11729 if (decalsystem->model)
11730 R_DecalSystem_Reset(decalsystem);
11734 if (decalsystem->model != model)
11735 R_DecalSystem_Reset(decalsystem);
11736 decalsystem->model = model;
11738 RSurf_ActiveModelEntity(ent, false, false, false);
11740 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11741 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11742 VectorNormalize(localnormal);
11743 localsize = worldsize*rsurface.inversematrixscale;
11744 localmins[0] = localorigin[0] - localsize;
11745 localmins[1] = localorigin[1] - localsize;
11746 localmins[2] = localorigin[2] - localsize;
11747 localmaxs[0] = localorigin[0] + localsize;
11748 localmaxs[1] = localorigin[1] + localsize;
11749 localmaxs[2] = localorigin[2] + localsize;
11751 //VectorCopy(localnormal, planes[4]);
11752 //VectorVectors(planes[4], planes[2], planes[0]);
11753 AnglesFromVectors(angles, localnormal, NULL, false);
11754 AngleVectors(angles, planes[0], planes[2], planes[4]);
11755 VectorNegate(planes[0], planes[1]);
11756 VectorNegate(planes[2], planes[3]);
11757 VectorNegate(planes[4], planes[5]);
11758 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11759 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11760 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11761 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11762 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11763 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11768 matrix4x4_t forwardprojection;
11769 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11770 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11775 float projectionvector[4][3];
11776 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11777 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11778 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11779 projectionvector[0][0] = planes[0][0] * ilocalsize;
11780 projectionvector[0][1] = planes[1][0] * ilocalsize;
11781 projectionvector[0][2] = planes[2][0] * ilocalsize;
11782 projectionvector[1][0] = planes[0][1] * ilocalsize;
11783 projectionvector[1][1] = planes[1][1] * ilocalsize;
11784 projectionvector[1][2] = planes[2][1] * ilocalsize;
11785 projectionvector[2][0] = planes[0][2] * ilocalsize;
11786 projectionvector[2][1] = planes[1][2] * ilocalsize;
11787 projectionvector[2][2] = planes[2][2] * ilocalsize;
11788 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11789 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11790 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11791 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11795 dynamic = model->surfmesh.isanimated;
11796 vertex3f = rsurface.modelvertex3f;
11797 numsurfacelist = model->nummodelsurfaces;
11798 surfacelist = model->sortedmodelsurfaces;
11799 surfaces = model->data_surfaces;
11800 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11802 surfaceindex = surfacelist[surfacelistindex];
11803 surface = surfaces + surfaceindex;
11804 // check cull box first because it rejects more than any other check
11805 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11807 // skip transparent surfaces
11808 texture = surface->texture;
11809 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11811 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11813 numtriangles = surface->num_triangles;
11814 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11816 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11818 index = 3*e[cornerindex];
11819 VectorCopy(vertex3f + index, v[cornerindex]);
11822 //TriangleNormal(v[0], v[1], v[2], normal);
11823 //if (DotProduct(normal, localnormal) < 0.0f)
11825 // clip by each of the box planes formed from the projection matrix
11826 // if anything survives, we emit the decal
11827 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]);
11830 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]);
11833 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]);
11836 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]);
11839 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]);
11842 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]);
11845 // some part of the triangle survived, so we have to accept it...
11848 // dynamic always uses the original triangle
11850 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11852 index = 3*e[cornerindex];
11853 VectorCopy(vertex3f + index, v[cornerindex]);
11856 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11858 // convert vertex positions to texcoords
11859 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11860 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11861 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11862 // calculate distance fade from the projection origin
11863 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11864 f = bound(0.0f, f, 1.0f);
11865 c[cornerindex][0] = r * f;
11866 c[cornerindex][1] = g * f;
11867 c[cornerindex][2] = b * f;
11868 c[cornerindex][3] = 1.0f;
11869 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11872 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);
11874 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11875 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);
11880 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11881 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)
11883 int renderentityindex;
11884 float worldmins[3];
11885 float worldmaxs[3];
11886 entity_render_t *ent;
11888 if (!cl_decals_newsystem.integer)
11891 worldmins[0] = worldorigin[0] - worldsize;
11892 worldmins[1] = worldorigin[1] - worldsize;
11893 worldmins[2] = worldorigin[2] - worldsize;
11894 worldmaxs[0] = worldorigin[0] + worldsize;
11895 worldmaxs[1] = worldorigin[1] + worldsize;
11896 worldmaxs[2] = worldorigin[2] + worldsize;
11898 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11900 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11902 ent = r_refdef.scene.entities[renderentityindex];
11903 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11906 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11910 typedef struct r_decalsystem_splatqueue_s
11912 vec3_t worldorigin;
11913 vec3_t worldnormal;
11919 r_decalsystem_splatqueue_t;
11921 int r_decalsystem_numqueued = 0;
11922 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11924 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)
11926 r_decalsystem_splatqueue_t *queue;
11928 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11931 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11932 VectorCopy(worldorigin, queue->worldorigin);
11933 VectorCopy(worldnormal, queue->worldnormal);
11934 Vector4Set(queue->color, r, g, b, a);
11935 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11936 queue->worldsize = worldsize;
11937 queue->decalsequence = cl.decalsequence++;
11940 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11943 r_decalsystem_splatqueue_t *queue;
11945 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11946 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);
11947 r_decalsystem_numqueued = 0;
11950 extern cvar_t cl_decals_max;
11951 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11954 decalsystem_t *decalsystem = &ent->decalsystem;
11961 if (!decalsystem->numdecals)
11964 if (r_showsurfaces.integer)
11967 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11969 R_DecalSystem_Reset(decalsystem);
11973 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11974 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11976 if (decalsystem->lastupdatetime)
11977 frametime = (cl.time - decalsystem->lastupdatetime);
11980 decalsystem->lastupdatetime = cl.time;
11981 decal = decalsystem->decals;
11982 numdecals = decalsystem->numdecals;
11984 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11986 if (decal->color4ub[0][3])
11988 decal->lived += frametime;
11989 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11991 memset(decal, 0, sizeof(*decal));
11992 if (decalsystem->freedecal > i)
11993 decalsystem->freedecal = i;
11997 decal = decalsystem->decals;
11998 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12001 // collapse the array by shuffling the tail decals into the gaps
12004 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12005 decalsystem->freedecal++;
12006 if (decalsystem->freedecal == numdecals)
12008 decal[decalsystem->freedecal] = decal[--numdecals];
12011 decalsystem->numdecals = numdecals;
12013 if (numdecals <= 0)
12015 // if there are no decals left, reset decalsystem
12016 R_DecalSystem_Reset(decalsystem);
12020 extern skinframe_t *decalskinframe;
12021 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12024 decalsystem_t *decalsystem = &ent->decalsystem;
12033 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12036 numdecals = decalsystem->numdecals;
12040 if (r_showsurfaces.integer)
12043 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12045 R_DecalSystem_Reset(decalsystem);
12049 // if the model is static it doesn't matter what value we give for
12050 // wantnormals and wanttangents, so this logic uses only rules applicable
12051 // to a model, knowing that they are meaningless otherwise
12052 if (ent == r_refdef.scene.worldentity)
12053 RSurf_ActiveWorldEntity();
12055 RSurf_ActiveModelEntity(ent, false, false, false);
12057 decalsystem->lastupdatetime = cl.time;
12058 decal = decalsystem->decals;
12060 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12062 // update vertex positions for animated models
12063 v3f = decalsystem->vertex3f;
12064 c4f = decalsystem->color4f;
12065 t2f = decalsystem->texcoord2f;
12066 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12068 if (!decal->color4ub[0][3])
12071 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12074 // update color values for fading decals
12075 if (decal->lived >= cl_decals_time.value)
12077 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12078 alpha *= (1.0f/255.0f);
12081 alpha = 1.0f/255.0f;
12083 c4f[ 0] = decal->color4ub[0][0] * alpha;
12084 c4f[ 1] = decal->color4ub[0][1] * alpha;
12085 c4f[ 2] = decal->color4ub[0][2] * alpha;
12087 c4f[ 4] = decal->color4ub[1][0] * alpha;
12088 c4f[ 5] = decal->color4ub[1][1] * alpha;
12089 c4f[ 6] = decal->color4ub[1][2] * alpha;
12091 c4f[ 8] = decal->color4ub[2][0] * alpha;
12092 c4f[ 9] = decal->color4ub[2][1] * alpha;
12093 c4f[10] = decal->color4ub[2][2] * alpha;
12096 t2f[0] = decal->texcoord2f[0][0];
12097 t2f[1] = decal->texcoord2f[0][1];
12098 t2f[2] = decal->texcoord2f[1][0];
12099 t2f[3] = decal->texcoord2f[1][1];
12100 t2f[4] = decal->texcoord2f[2][0];
12101 t2f[5] = decal->texcoord2f[2][1];
12103 // update vertex positions for animated models
12104 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12106 e = rsurface.modelelement3i + 3*decal->triangleindex;
12107 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12108 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12109 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12113 VectorCopy(decal->vertex3f[0], v3f);
12114 VectorCopy(decal->vertex3f[1], v3f + 3);
12115 VectorCopy(decal->vertex3f[2], v3f + 6);
12118 if (r_refdef.fogenabled)
12120 alpha = RSurf_FogVertex(v3f);
12121 VectorScale(c4f, alpha, c4f);
12122 alpha = RSurf_FogVertex(v3f + 3);
12123 VectorScale(c4f + 4, alpha, c4f + 4);
12124 alpha = RSurf_FogVertex(v3f + 6);
12125 VectorScale(c4f + 8, alpha, c4f + 8);
12136 r_refdef.stats.drawndecals += numtris;
12138 // now render the decals all at once
12139 // (this assumes they all use one particle font texture!)
12140 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);
12141 R_Mesh_ResetTextureState();
12142 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12143 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12144 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12145 GL_DepthMask(false);
12146 GL_DepthRange(0, 1);
12147 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12148 GL_DepthTest(true);
12149 GL_CullFace(GL_NONE);
12150 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12151 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12152 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12156 static void R_DrawModelDecals(void)
12160 // fade faster when there are too many decals
12161 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12162 for (i = 0;i < r_refdef.scene.numentities;i++)
12163 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12165 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12166 for (i = 0;i < r_refdef.scene.numentities;i++)
12167 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12168 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12170 R_DecalSystem_ApplySplatEntitiesQueue();
12172 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12173 for (i = 0;i < r_refdef.scene.numentities;i++)
12174 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12176 r_refdef.stats.totaldecals += numdecals;
12178 if (r_showsurfaces.integer)
12181 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12183 for (i = 0;i < r_refdef.scene.numentities;i++)
12185 if (!r_refdef.viewcache.entityvisible[i])
12187 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12188 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12192 extern cvar_t mod_collision_bih;
12193 void R_DrawDebugModel(void)
12195 entity_render_t *ent = rsurface.entity;
12196 int i, j, k, l, flagsmask;
12197 const msurface_t *surface;
12198 dp_model_t *model = ent->model;
12201 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12203 R_Mesh_ColorPointer(NULL, 0, 0);
12204 R_Mesh_ResetTextureState();
12205 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12206 GL_DepthRange(0, 1);
12207 GL_DepthTest(!r_showdisabledepthtest.integer);
12208 GL_DepthMask(false);
12209 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12211 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12215 qboolean cullbox = ent == r_refdef.scene.worldentity;
12216 const q3mbrush_t *brush;
12217 const bih_t *bih = &model->collision_bih;
12218 const bih_leaf_t *bihleaf;
12219 float vertex3f[3][3];
12220 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12222 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12224 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12226 switch (bihleaf->type)
12229 brush = model->brush.data_brushes + bihleaf->itemindex;
12230 if (brush->colbrushf && brush->colbrushf->numtriangles)
12232 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12233 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12234 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12237 case BIH_COLLISIONTRIANGLE:
12238 triangleindex = bihleaf->itemindex;
12239 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12240 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12241 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12242 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12243 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12244 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12246 case BIH_RENDERTRIANGLE:
12247 triangleindex = bihleaf->itemindex;
12248 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12249 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12250 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12251 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12252 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12253 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12259 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12261 if (r_showtris.integer || r_shownormals.integer)
12263 if (r_showdisabledepthtest.integer)
12265 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12266 GL_DepthMask(false);
12270 GL_BlendFunc(GL_ONE, GL_ZERO);
12271 GL_DepthMask(true);
12273 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12275 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12277 rsurface.texture = R_GetCurrentTexture(surface->texture);
12278 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12280 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12281 if (r_showtris.value > 0)
12283 if (!rsurface.texture->currentlayers->depthmask)
12284 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12285 else if (ent == r_refdef.scene.worldentity)
12286 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12288 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12289 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12290 R_Mesh_ColorPointer(NULL, 0, 0);
12291 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12292 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12293 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12294 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);
12295 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12298 if (r_shownormals.value < 0)
12300 qglBegin(GL_LINES);
12301 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12303 VectorCopy(rsurface.vertex3f + l * 3, v);
12304 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12305 qglVertex3f(v[0], v[1], v[2]);
12306 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12307 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12308 qglVertex3f(v[0], v[1], v[2]);
12313 if (r_shownormals.value > 0)
12315 qglBegin(GL_LINES);
12316 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12318 VectorCopy(rsurface.vertex3f + l * 3, v);
12319 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12320 qglVertex3f(v[0], v[1], v[2]);
12321 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12322 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12323 qglVertex3f(v[0], v[1], v[2]);
12327 qglBegin(GL_LINES);
12328 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12330 VectorCopy(rsurface.vertex3f + l * 3, v);
12331 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12332 qglVertex3f(v[0], v[1], v[2]);
12333 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12334 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12335 qglVertex3f(v[0], v[1], v[2]);
12339 qglBegin(GL_LINES);
12340 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12342 VectorCopy(rsurface.vertex3f + l * 3, v);
12343 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12344 qglVertex3f(v[0], v[1], v[2]);
12345 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12346 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12347 qglVertex3f(v[0], v[1], v[2]);
12354 rsurface.texture = NULL;
12358 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12359 int r_maxsurfacelist = 0;
12360 const msurface_t **r_surfacelist = NULL;
12361 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12363 int i, j, endj, flagsmask;
12364 dp_model_t *model = r_refdef.scene.worldmodel;
12365 msurface_t *surfaces;
12366 unsigned char *update;
12367 int numsurfacelist = 0;
12371 if (r_maxsurfacelist < model->num_surfaces)
12373 r_maxsurfacelist = model->num_surfaces;
12375 Mem_Free((msurface_t**)r_surfacelist);
12376 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12379 RSurf_ActiveWorldEntity();
12381 surfaces = model->data_surfaces;
12382 update = model->brushq1.lightmapupdateflags;
12384 // update light styles on this submodel
12385 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12387 model_brush_lightstyleinfo_t *style;
12388 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12390 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12392 int *list = style->surfacelist;
12393 style->value = r_refdef.scene.lightstylevalue[style->style];
12394 for (j = 0;j < style->numsurfaces;j++)
12395 update[list[j]] = true;
12400 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12404 R_DrawDebugModel();
12405 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12409 rsurface.uselightmaptexture = false;
12410 rsurface.texture = NULL;
12411 rsurface.rtlight = NULL;
12412 numsurfacelist = 0;
12413 // add visible surfaces to draw list
12414 for (i = 0;i < model->nummodelsurfaces;i++)
12416 j = model->sortedmodelsurfaces[i];
12417 if (r_refdef.viewcache.world_surfacevisible[j])
12418 r_surfacelist[numsurfacelist++] = surfaces + j;
12420 // update lightmaps if needed
12421 if (model->brushq1.firstrender)
12423 model->brushq1.firstrender = false;
12424 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12426 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12430 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12431 if (r_refdef.viewcache.world_surfacevisible[j])
12433 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12435 // don't do anything if there were no surfaces
12436 if (!numsurfacelist)
12438 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12441 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12442 GL_AlphaTest(false);
12444 // add to stats if desired
12445 if (r_speeds.integer && !skysurfaces && !depthonly)
12447 r_refdef.stats.world_surfaces += numsurfacelist;
12448 for (j = 0;j < numsurfacelist;j++)
12449 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12452 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12455 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12457 int i, j, endj, flagsmask;
12458 dp_model_t *model = ent->model;
12459 msurface_t *surfaces;
12460 unsigned char *update;
12461 int numsurfacelist = 0;
12465 if (r_maxsurfacelist < model->num_surfaces)
12467 r_maxsurfacelist = model->num_surfaces;
12469 Mem_Free((msurface_t **)r_surfacelist);
12470 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12473 // if the model is static it doesn't matter what value we give for
12474 // wantnormals and wanttangents, so this logic uses only rules applicable
12475 // to a model, knowing that they are meaningless otherwise
12476 if (ent == r_refdef.scene.worldentity)
12477 RSurf_ActiveWorldEntity();
12478 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12479 RSurf_ActiveModelEntity(ent, false, false, false);
12481 RSurf_ActiveModelEntity(ent, true, true, true);
12482 else if (depthonly)
12484 switch (vid.renderpath)
12486 case RENDERPATH_GL20:
12487 case RENDERPATH_CGGL:
12488 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12490 case RENDERPATH_GL13:
12491 case RENDERPATH_GL11:
12492 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12498 switch (vid.renderpath)
12500 case RENDERPATH_GL20:
12501 case RENDERPATH_CGGL:
12502 RSurf_ActiveModelEntity(ent, true, true, false);
12504 case RENDERPATH_GL13:
12505 case RENDERPATH_GL11:
12506 RSurf_ActiveModelEntity(ent, true, false, false);
12511 surfaces = model->data_surfaces;
12512 update = model->brushq1.lightmapupdateflags;
12514 // update light styles
12515 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12517 model_brush_lightstyleinfo_t *style;
12518 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12520 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12522 int *list = style->surfacelist;
12523 style->value = r_refdef.scene.lightstylevalue[style->style];
12524 for (j = 0;j < style->numsurfaces;j++)
12525 update[list[j]] = true;
12530 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12534 R_DrawDebugModel();
12535 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12539 rsurface.uselightmaptexture = false;
12540 rsurface.texture = NULL;
12541 rsurface.rtlight = NULL;
12542 numsurfacelist = 0;
12543 // add visible surfaces to draw list
12544 for (i = 0;i < model->nummodelsurfaces;i++)
12545 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12546 // don't do anything if there were no surfaces
12547 if (!numsurfacelist)
12549 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12552 // update lightmaps if needed
12556 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12561 R_BuildLightMap(ent, surfaces + j);
12566 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12568 R_BuildLightMap(ent, surfaces + j);
12569 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12570 GL_AlphaTest(false);
12572 // add to stats if desired
12573 if (r_speeds.integer && !skysurfaces && !depthonly)
12575 r_refdef.stats.entities_surfaces += numsurfacelist;
12576 for (j = 0;j < numsurfacelist;j++)
12577 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12580 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12583 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12585 static texture_t texture;
12586 static msurface_t surface;
12587 const msurface_t *surfacelist = &surface;
12589 // fake enough texture and surface state to render this geometry
12591 texture.update_lastrenderframe = -1; // regenerate this texture
12592 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12593 texture.currentskinframe = skinframe;
12594 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12595 texture.offsetmapping = OFFSETMAPPING_OFF;
12596 texture.offsetscale = 1;
12597 texture.specularscalemod = 1;
12598 texture.specularpowermod = 1;
12600 surface.texture = &texture;
12601 surface.num_triangles = numtriangles;
12602 surface.num_firsttriangle = firsttriangle;
12603 surface.num_vertices = numvertices;
12604 surface.num_firstvertex = firstvertex;
12607 rsurface.texture = R_GetCurrentTexture(surface.texture);
12608 rsurface.uselightmaptexture = false;
12609 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12612 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)
12614 static msurface_t surface;
12615 const msurface_t *surfacelist = &surface;
12617 // fake enough texture and surface state to render this geometry
12619 surface.texture = texture;
12620 surface.num_triangles = numtriangles;
12621 surface.num_firsttriangle = firsttriangle;
12622 surface.num_vertices = numvertices;
12623 surface.num_firstvertex = firstvertex;
12626 rsurface.texture = R_GetCurrentTexture(surface.texture);
12627 rsurface.uselightmaptexture = false;
12628 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);